Hibernate mappings and the XDoclet merge option
lukas The project I’m currently working on uses XDoclet 1.2 to generate hibernate mapping and configuration files. Up to now, when our mapping requirements were too complex for XDoclet we would supplement our Java bean hibernate annotations with custom hbm.xml files and include those within an <otherMapping> element inside a <hibernatecfg> tag of the HibernateDocletTask.
Ant would then build most of the hbm.xml files from the bean annotations but also copy the handful of handcoded custom ones into the bin dir.
An improvement on this is to leave most of the hibernate annotations in the bean classes and have HibernateDoclet merge only the required mappings into the hibernate mapping files. The definition of the Hibernate XDoclet task is at thislink.
build.xml:
<target name="xdoclet-generate" depends="init" description="generate xdoclet hibernate mappings"> <!-- location of xdoclet libraries --> <path id="xdoclet.task.classpath"> <fileset dir="${xdoclet.lib.dir}"> <include name="*.jar" /> </fileset> </path> <taskdef name="hibernatedoclet" classname="xdoclet.modules.hibernate.HibernateDocletTask" classpathref="xdoclet.task.classpath" /> <hibernatedoclet destdir="${build.classes.dir}" verbose="true"> <!-- defines the files handled by xdoclet --> <fileset dir="${basedir}/src"> <include name="**/*.java"/> </fileset> <!-- generate the mapping files --> <hibernate version="3.0" validateXML="true" mergeDir="${source.dir}" /> <!-- generate hibernate config file --> <hibernatecfg destinationFile="hibernate.cfg.xml" validateXML="true" version="3.0" transactionManagerFactory="org.hibernate.transaction.CMTTransactionFactory" transactionManagerLookup="org.hibernate.transaction.WebSphereExtendedJTATransactionLookup" dataSource="jdbc/schemaName" showSql="true" dialect="org.hibernate.dialect.DB2Dialect" > <otherProperty name="hibernate.transaction.flush_before_completion" value="true" /> <otherProperty name="hibernate.transaction.auto_close_session" value="true" /> <otherMapping name="resource" value="com/mycompany/domain/model/ComplexDomainObject.hbm.xml"/> <otherMapping name="resource" value="com/mycompany/domain/model/CommonDefinitions.hbm.xml"/> </hibernatecfg> </hibernatedoclet> </target>
Notice how the above task defines a mergeDir at the hibernate element level. XDoclet will scan all dirs below this for any custom xml files to be merged into the hibernate mappings.
- hibernate-properties.xml - goes into the root of the mergeDir. Anything in there is included in ALL mapping files.
- hibernate-properties-{0}.xml - must be located in a directory underneath the mergeDir, mirroring the fully qualified package/name of the {0} bean class. (This is so that two classes from different packages could be mapped correctly).
I can now define any mapping not supported with annotations in 1.2 (e.g. a hibernate-filter) in a separate hibernate-properties-{0}.xml file:
hibernate-properties-NotSoSimpleDomainObject.xml:
<filter name="limitByCurrentDataVersionFilter" condition=":dataVersion = dataversion"/>and xdoclet will merge it into the mapping file at build:
NotSoSimpleDomainObject.hbm.xml:
<hibernate-mapping> <class name="com.mycompany.domain.model.NotSoSimpleDomainObject" table="NOT_SIMPLE_DOMAIN"> <id name="id" column="NOT_SIMPLE_DOMAIN_ID"> <generator class="identity"> </generator> </id> <property name="codeValue" column="CODE_VALUE" /> <property name="description" column="VALUE_DESC" /> <filter name="limitByCurrentDataVersionFilter" condition=":dataVersion = dataversion"/> </class> </hibernate-mapping>
For completeness sake, remember that you also need a filter definition inside a hibernate-mapping element (this is a global definition so can be anywhere - even in its own mapping file). I import this using the otherMapping element from a CommonDefinitions.hbm.xml in the Ant task above.
CommonDefinitions.hbm.xml:
<filter-def name="activatedFilter"> <filter-param name="activatedParam" type="boolean"/> </filter-def>
Posted in hibernate, programming |