1 /* Copyright 2004-2005 Graeme Rocher
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
15 package org
.codehaus
.groovy
.grails
.orm
.hibernate
.cfg
;
17 import groovy
.lang
.GroovyObject
;
18 import org
.apache
.commons
.logging
.Log
;
19 import org
.apache
.commons
.logging
.LogFactory
;
20 import org
.codehaus
.groovy
.grails
.commons
.DomainClassArtefactHandler
;
21 import org
.codehaus
.groovy
.grails
.commons
.GrailsApplication
;
22 import org
.codehaus
.groovy
.grails
.commons
.GrailsDomainClass
;
23 import org
.codehaus
.groovy
.grails
.commons
.metaclass
.DynamicMethods
;
24 import org
.codehaus
.groovy
.grails
.commons
.spring
.GrailsRuntimeConfigurator
;
25 import org
.codehaus
.groovy
.grails
.orm
.hibernate
.GrailsHibernateDomainClass
;
26 import org
.codehaus
.groovy
.grails
.orm
.hibernate
.metaclass
.DomainClassMethods
;
27 import org
.hibernate
.Criteria
;
28 import org
.hibernate
.EntityMode
;
29 import org
.hibernate
.FetchMode
;
30 import org
.hibernate
.SessionFactory
;
31 import org
.hibernate
.criterion
.Order
;
32 import org
.hibernate
.metadata
.ClassMetadata
;
33 import org
.springframework
.beans
.SimpleTypeConverter
;
34 import org
.springframework
.context
.ApplicationContext
;
36 import java
.beans
.IntrospectionException
;
37 import java
.lang
.reflect
.Modifier
;
38 import java
.util
.Collection
;
39 import java
.util
.HashMap
;
40 import java
.util
.Iterator
;
44 * A class containing utility methods for configuring Hibernate inside Grails
46 * @author Graeme Rocher
49 * Created: Jan 19, 2007
52 public class GrailsHibernateUtil
{
53 private static final Log LOG
= LogFactory
.getLog(GrailsHibernateUtil
.class);
54 public static SimpleTypeConverter converter
= new SimpleTypeConverter();
55 public static final String ARGUMENT_MAX
= "max";
56 public static final String ARGUMENT_OFFSET
= "offset";
57 public static final String ARGUMENT_ORDER
= "order";
58 public static final String ARGUMENT_SORT
= "sort";
59 public static final String ORDER_DESC
= "desc";
60 public static final String ORDER_ASC
= "asc";
61 public static final String ARGUMENT_FETCH
= "fetch";
62 public static final String ARGUMENT_IGNORE_CASE
= "ignoreCase";
64 public static void configureDynamicMethods(SessionFactory sessionFactory
, GrailsApplication application
) {
65 LOG
.trace("Configuring dynamic methods");
66 // if its not a grails domain class and one written in java then add it
68 Collection classMetaData
= sessionFactory
.getAllClassMetadata().values();
69 for (Iterator i
= classMetaData
.iterator(); i
.hasNext();) {
70 ClassMetadata cmd
= (ClassMetadata
) i
.next();
72 Class persistentClass
= cmd
.getMappedClass(EntityMode
.POJO
);
73 configureDynamicMethodsFor(sessionFactory
, application
, persistentClass
);
79 * Configures dynamic methods on all Hibernate mapped domain classes that are found in the application context
81 * @param applicationContext The session factory instance
82 * @param application The grails application instance
84 public static void configureDynamicMethods(ApplicationContext applicationContext
, GrailsApplication application
) {
85 LOG
.trace("Configuring dynamic methods");
86 if (applicationContext
== null)
87 throw new IllegalArgumentException("Cannot configure dynamic methods for null ApplicationContext");
89 SessionFactory sessionFactory
= (SessionFactory
) applicationContext
.getBean(GrailsRuntimeConfigurator
.SESSION_FACTORY_BEAN
);
91 configureDynamicMethods(sessionFactory
, application
);
94 public static DynamicMethods
configureDynamicMethodsFor(SessionFactory sessionFactory
, GrailsApplication application
, Class persistentClass
) {
95 if (LOG
.isTraceEnabled()) {
96 LOG
.trace("Registering dynamic methods on class [" + persistentClass
+ "]");
98 DynamicMethods dm
= null;
100 dm
= new DomainClassMethods(application
, persistentClass
, sessionFactory
, application
.getClassLoader());
101 } catch (IntrospectionException e
) {
102 LOG
.warn("Introspection exception registering dynamic methods for [" + persistentClass
+ "]:" + e
.getMessage(), e
);
107 public static void configureHibernateDomainClasses(SessionFactory sessionFactory
, GrailsApplication application
) {
108 Map hibernateDomainClassMap
= new HashMap();
109 for (Iterator i
= sessionFactory
.getAllClassMetadata().values().iterator(); i
.hasNext();) {
110 ClassMetadata classMetadata
= (ClassMetadata
) i
.next();
111 configureDomainClass(sessionFactory
, application
, classMetadata
, classMetadata
.getMappedClass(EntityMode
.POJO
), hibernateDomainClassMap
);
113 configureInheritanceMappings(hibernateDomainClassMap
);
116 public static void configureInheritanceMappings(Map hibernateDomainClassMap
) {
117 // now get through all domainclasses, and add all subclasses to root class
118 for (Iterator it
= hibernateDomainClassMap
.values().iterator(); it
.hasNext();) {
119 GrailsDomainClass baseClass
= (GrailsDomainClass
) it
.next();
120 if (!baseClass
.isRoot()) {
121 Class superClass
= baseClass
122 .getClazz().getSuperclass();
125 while (!superClass
.equals(Object
.class) && !superClass
.equals(GroovyObject
.class)) {
126 GrailsDomainClass gdc
= (GrailsDomainClass
) hibernateDomainClassMap
.get(superClass
.getName());
128 if (gdc
== null || gdc
.getSubClasses() == null) {
129 LOG
.error("did not find superclass names when mapping inheritance....");
132 gdc
.getSubClasses().add(baseClass
);
133 superClass
= superClass
.getSuperclass();
139 private static void configureDomainClass(SessionFactory sessionFactory
, GrailsApplication application
, ClassMetadata cmd
, Class persistentClass
, Map hibernateDomainClassMap
) {
140 if (!Modifier
.isAbstract(persistentClass
.getModifiers())) {
141 LOG
.trace("Configuring domain class [" + persistentClass
+ "]");
142 GrailsDomainClass dc
= (GrailsDomainClass
) application
.getArtefact(DomainClassArtefactHandler
.TYPE
, persistentClass
.getName());
144 // a patch to add inheritance to this system
145 GrailsHibernateDomainClass ghdc
= new
146 GrailsHibernateDomainClass(persistentClass
, sessionFactory
, cmd
);
148 hibernateDomainClassMap
.put(persistentClass
.getName(),
151 dc
= (GrailsDomainClass
) application
.addArtefact(DomainClassArtefactHandler
.TYPE
, ghdc
);
156 public static void populateArgumentsForCriteria(Criteria c
, Map argMap
) {
158 Integer maxParam
= null;
159 Integer offsetParam
= null;
160 if(argMap
.containsKey(ARGUMENT_MAX
)) {
161 maxParam
= (Integer
)converter
.convertIfNecessary(argMap
.get(ARGUMENT_MAX
),Integer
.class);
163 if(argMap
.containsKey(ARGUMENT_OFFSET
)) {
164 offsetParam
= (Integer
)converter
.convertIfNecessary(argMap
.get(ARGUMENT_OFFSET
),Integer
.class);
166 String orderParam
= (String
)argMap
.get(ARGUMENT_ORDER
);
167 Object fetchObj
= argMap
.get(ARGUMENT_FETCH
);
168 if(fetchObj
instanceof Map
) {
169 Map fetch
= (Map
)fetchObj
;
170 for (Iterator i
= fetch
.keySet().iterator(); i
.hasNext();) {
171 String associationName
= (String
) i
.next();
172 c
.setFetchMode(associationName
, getFetchMode(fetch
.get(associationName
)));
176 final String sort
= (String
)argMap
.get(ARGUMENT_SORT
);
177 final String order
= ORDER_DESC
.equalsIgnoreCase(orderParam
) ? ORDER_DESC
: ORDER_ASC
;
178 final int max
= maxParam
== null ?
-1 : maxParam
.intValue();
179 final int offset
= offsetParam
== null ?
-1 : offsetParam
.intValue();
181 c
.setMaxResults(max
);
183 c
.setFirstResult(offset
);
185 boolean ignoreCase
= true;
186 Object caseArg
= argMap
.get(ARGUMENT_IGNORE_CASE
);
187 if(caseArg
instanceof Boolean
) {
188 ignoreCase
= ((Boolean
)caseArg
).booleanValue();
190 if(ORDER_DESC
.equals(order
)) {
191 c
.addOrder( ignoreCase ? Order
.desc(sort
).ignoreCase() : Order
.desc(sort
));
194 c
.addOrder( ignoreCase ? Order
.asc(sort
).ignoreCase() : Order
.asc(sort
) );
200 * Will retrieve the fetch mode for the specified instance other wise return the
203 * @param object The object, converted to a string
204 * @return The FetchMode
206 public static FetchMode
getFetchMode(Object object
) {
207 String name
= object
!= null ? object
.toString() : "default";
208 if(name
.equals(FetchMode
.JOIN
.toString()) || name
.equals("eager")) {
209 return FetchMode
.JOIN
;
211 else if(name
.equals(FetchMode
.SELECT
.toString()) || name
.equals("lazy")) {
212 return FetchMode
.SELECT
;
214 return FetchMode
.DEFAULT
;