如果你并不打算使用类继承结构并不是很有必要阅读本文。请先阅读我写的另一篇文章 "使用hibernate扩展工具hbm2javatask根据配置文件生成持久化对象类(2.1.2)"1.在文档第8章(hibernate/doc/reference/zh-cn/html/inheritance.html)有提到
“每个子类一个表”的映射是这样的:
<class name="payment" table="payment"> <id name="id" type="long" column="payment_id"> <generator class="native"/> </id> <property name="amount" column="amount"/> ... <joined-subclass name="creditcardpayment" table="credit_payment"> <key column="payment_id"/> ... </joined-subclass> <joined-subclass name="cashpayment" table="cash_payment"> <key column="payment_id"/> ... </joined-subclass> <joined-subclass name="chequepayment" table="cheque_payment"> <key column="payment_id"/> ... </joined-subclass></class>
2.文档第5章(hibernate/doc/reference/zh-cn/html/mapping.html)有提到
允许在独立的映射文档中定义subclass和joined-subclass,直接位于hibernate-mapping下。这就可以让你每次扩展你的类层次的时候,加入新的映射文件就行了。在子类的映射中你必须指定一个extents属性,指明先前已经映射过的超类。使用这个功能的时候,一定要注意映射文件的排序是非常重要的!
<hibernate-mapping> <subclass name="eg.subclass.domesticcat" extends="eg.cat" discriminator-value="d"> <property name="name" type="string"/> </subclass></hibernate-mapping>
3.根据以上两点,偶根据第8章的payment创建了一个工程,把joined-subclass移了出来,现在工程目录结构如下 payment <dir>|-src <dir>|-hbm <dir> |-payment <dir> |-payment.hbm.xml |-creditcardpayment.hbm.xml |-cashpayment.hbm.xml|-classes <dir>|-lib <dir>|-build.xml|-hibernate.codegen.xml|-log4j.properties4. 本文不再重复build.xml, hibernate.codegen.xml, log4j.properties三个文件的内容。可在"使用hibernate扩展工具hbm2javatask根据配置文件生成持久化对象类(2.1.2)"一文查看这三个文件的内容。此处仅列出.hbm.xml文件内容。 4.1 payment.hbm.xml<?xml version="1.0" encoding="gbk"?><!doctype hibernate-mapping public "-//hibernate/hibernate mapping dtd//en" "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"><hibernate-mapping> <class name="payment.payment" table="payment"> <id name="id" type="long" column="payment_id"> <generator class="native"/> </id> <property name="amount" column="amount" type="long"/> </class></hibernate-mapping> 4.2 creditcardpayment.hbm.xml
<?xml version="1.0" encoding="gbk"?><!doctype hibernate-mapping public "-//hibernate/hibernate mapping dtd//en" "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"><hibernate-mapping><joined-subclass name="payment.creditcardpayment" table="credit_payment" extends="payment.payment"> <key column="payment_id"/></joined-subclass></hibernate-mapping>
4.3 cashpayment.hbm.xml
<?xml version="1.0" encoding="gbk"?><!doctype hibernate-mapping public "-//hibernate/hibernate mapping dtd//en" "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"><hibernate-mapping><joined-subclass name="payment.cashpayment" table="cash_payment" extends="payment.payment"> <key column="payment_id"/></joined-subclass></hibernate-mapping>
5.在命令行进入工程目录,运行ant,发生错误,关键提示如下: net.sf.hibernate.mappingexception: cannot extend unmapped class payment.payment6.查错过程我就不说了,比较无聊,只说一下问题出在哪里 6.1 hbm2javatask里对配置文件列表做了循环,每个文件单独处理,所以有关联的类就找不到了。 6.2 但是codegenerator类也有不妥,没有考虑文件排列问题,因为子类可能先于父类被处理。7.下面帖出两个修改过的文件代码。在修改的地方加了中文注释。 7.1 net.sf.hibernate.tool.hbm2java.hbm2javatask
package net.sf.hibernate.tool.hbm2java;import java.io.file;import java.io.printwriter;import java.io.stringwriter;import java.util.arraylist;import java.util.list;import org.apache.tools.ant.buildexception;import org.apache.tools.ant.directoryscanner;import org.apache.tools.ant.task;import org.apache.tools.ant.types.fileset;import org.apache.tools.ant.types.path;import org.apache.tools.ant.types.reference;import org.apache.commons.logging.log;import org.apache.commons.logging.logfactory;/** * task for hbm2java (hibernates codegenerator) * * * @author gbegley and max * */public class hbm2javatask extends task { private static final log log = logfactory.getlog(codegenerator.class); private file configurationfile; private path compileclasspath; private file outputdir; private list filesets = new arraylist(); /** * set a hbm2java <literal>config.xml</literal> configuration file * @param the file name */ public void setconfig(file configurationfile) { this.configurationfile = configurationfile; } /** * set the classpath to be used for this compilation. * * @param classpath an ant path object containing the compilation classpath. */ public void setclasspath(path classpath) { if (compileclasspath == null) { compileclasspath = classpath; } else { compileclasspath.append(classpath); } } /** gets the classpath to be used for this compilation. */ public path getclasspath() { return compileclasspath; } /** * adds a path to the classpath. */ public path createclasspath() { if (compileclasspath == null) { compileclasspath = new path(getproject()); } return compileclasspath.createpath(); } /** * adds a reference to a classpath defined elsewhere. */ public void setclasspathref(reference r) { createclasspath().setrefid(r); } /** * adds a set of files to translate. */ public void addfileset(fileset set) { filesets.add(set); } /** * sets the output directory. * * @param bindirectory directory */ public void setoutput(file outdirectory) { this.outputdir = outdirectory; } public void execute() throws buildexception { list filelist = gettargetfiles(); if (filelist.size() == 0) return; log("processing " + filelist.size() + " files."); try { log("building hibernate objects"); //这个循环是错误1, //for (int i = 0; i < filelist.size(); i++) { // processfile(outputdir, (file) filelist.get(i)); //} //要修改processfile方法 processfile(outputdir, filelist); } catch (throwable t) { stringwriter sw = new stringwriter(); t.printstacktrace(new printwriter(sw)); throw new buildexception("caused by:/n" + sw.tostring()); } } /** * * * comment: * the initial ant task had some initial
闽公网安备 35060202000074号