bug? Hbm2JavaTask无法实现joined-subclass单独配置文件(2.1.2)

来源:互联网 发布:fbreader源码分析 编辑:程序博客网 时间:2024/06/06 02:57

如果你并不打算使用类继承结构并不是很有必要阅读本文。

请先阅读我写的另一篇文章
"使用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)有提到

允许在独立的映射文档中定义subclassjoined-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.properties


4. 本文不再重复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.Payment

6.查错过程我就不说了,比较无聊,只说一下问题出在哪里
  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 filtering on the hbm.xml/java names to only process the needed files.     * That is not possible to decide in the ant task without implementing the same logic present in hbm2java.     * Thus I've removed it and let it be something that hbm2java should do.     *      *      * @return     */    private List getTargetFiles() {        List l = new java.util.ArrayList();              // deal with the filesets              for (int i = 0; i < filesets.size(); i++) {                 FileSet fs = (FileSet) filesets.get(i);                 File parent = fs.getDir( getProject() );                 DirectoryScanner ds = fs.getDirectoryScanner(getProject());                 String[] files = ds.getIncludedFiles();                 for (int j = 0; j < files.length; j++) {                    File srcFile = new File( parent, files[j] );                    l.add( srcFile );                                     }              }              return l;    }    //修改了方法参数    private void processFile(File outputDir, List fileList) {        List args = new ArrayList();                if (outputDir != null) {            args.add("--output=" + outputDir.getAbsolutePath());        }        if (configurationFile != null) {            args.add("--config=" + configurationFile);        }                // 把所有文件都加入命令行参数        for ( int i = 0; i < fileList.size(); i++ ){            args.add(((File)fileList.get(i)).getAbsolutePath());        }                try         {            net.sf.hibernate.tool.hbm2java.CodeGenerator.main((String[]) args.toArray(new String[args.size()]));        } catch (Throwable t) {            StringWriter sw = new StringWriter();            t.printStackTrace(new PrintWriter(sw));            throw new BuildException("Caused by:/n" + sw.toString());        }    }}

  7.2 net.sf.hibernate.tool.hbm2java.CodeGenerator
/* * $Id: CodeGenerator.java,v 1.7 2004/03/22 20:41:47 maxcsaucdk Exp $ */package net.sf.hibernate.tool.hbm2java;import java.io.File;import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;import java.util.List;import net.sf.hibernate.MappingException;import net.sf.hibernate.util.DTDEntityResolver;import org.apache.commons.collections.MultiHashMap;import org.apache.commons.collections.MultiMap;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.jdom.Document;import org.jdom.Element;import org.jdom.input.SAXBuilder;import org.xml.sax.ErrorHandler;import org.xml.sax.SAXParseException;/** * */public class CodeGenerator {    private static final Log log = LogFactory.getLog(CodeGenerator.class);          public static void main(String[] args) {                    if(args.length==0) {              System.err.println("No arguments provided. Nothing to do. Exit.");              System.exit(-1);                        }        try {            ArrayList mappingFiles = new ArrayList();                SAXBuilder builder = new SAXBuilder(true);            builder.setEntityResolver( new DTDEntityResolver() );                        builder.setErrorHandler( new ErrorHandler() {                public void error(SAXParseException error) {                    log.error("Error parsing XML: " + error.getSystemId() + '(' + error.getLineNumber() + ')',error);                }                public void fatalError(SAXParseException error) {                     error(error);                 }                public void warning(SAXParseException error) {                    log.warn("Warning parsing XML: " + error.getSystemId() + '(' + error.getLineNumber() + ')' );                }            } );                        String outputDir = null;                List generators = new ArrayList();                MultiMap globalMetas = new MultiHashMap();            // parse command line parameters            for (int i = 0; i < args.length; i++) {                if (args[i].startsWith("--")) {                        if ( args[i].startsWith("--config=") ) {                        // parse config xml file                        builder.setValidation(false);                        Document document = builder.build( new File( args[i].substring(9) ) );                        globalMetas = MetaAttributeHelper.loadAndMergeMetaMap(document.getRootElement(), null);                        Iterator generateElements = document.getRootElement().getChildren("generate").iterator();                                                while (generateElements.hasNext()) {                            generators.add( new Generator( (Element) generateElements.next() ) );                        }                        builder.setValidation(true);                    }                    else if ( args[i].startsWith("--output=") ) {                        outputDir = args[i].substring(9);                    }                                        }                 else {                    mappingFiles.add( args[i] );                }            }                // if no config xml file, add a default generator            if (generators.size() == 0) {                generators.add( new Generator() );            }                        HashMap classMappings = new HashMap();            builder.setValidation(true);            // 这个循环是错误2            // 改成只处理class映射            for ( Iterator iter = mappingFiles.iterator(); iter.hasNext(); ) {                // parse the mapping file                File file = new File( (String) iter.next() );                log.debug(file.getAbsolutePath());                            Document document = builder.build( file);                                Element rootElement = document.getRootElement();                                org.jdom.Attribute a = rootElement.getAttribute("package");                String pkg = null;                if(a!=null) {                    pkg = a.getValue();                }                MappingElement me = new MappingElement(rootElement, null/**TODO-hbm2java: - should be config.xml**/);                Iterator classElements = rootElement.getChildren("class").iterator();                MultiMap mm = MetaAttributeHelper.loadAndMergeMetaMap(rootElement, globalMetas);                handleClass(pkg,me, classMappings, classElements, mm, false);            }                        // 复制了上一个循环            // 处理subclass和joined-class映射            for ( Iterator iter = mappingFiles.iterator(); iter.hasNext(); ) {                // parse the mapping file                File file = new File( (String) iter.next() );                            Document document = builder.build( file);                                Element rootElement = document.getRootElement();                                org.jdom.Attribute a = rootElement.getAttribute("package");                String pkg = null;                if(a!=null) {                    pkg = a.getValue();                }                MappingElement me = new MappingElement(rootElement, null/**TODO-hbm2java: - should be config.xml**/);                MultiMap mm = MetaAttributeHelper.loadAndMergeMetaMap(rootElement, globalMetas);                                Iterator classElements = rootElement.getChildren("subclass").iterator();                handleClass(pkg,me,classMappings, classElements, mm, true);                                classElements = rootElement.getChildren("joined-subclass").iterator();                handleClass(pkg,me,classMappings, classElements, mm, true);            }                // generate source files            for ( Iterator iterator = generators.iterator(); iterator.hasNext(); ) {                Generator g = (Generator) iterator.next();                g.setBaseDirName(outputDir);                g.generate(classMappings);            }        }         catch (Exception e) {            e.printStackTrace();        }    }    private static void handleClass(String classPackage, MappingElement me, HashMap classMappings, Iterator classElements, MultiMap mm, boolean extendz) throws MappingException {        while ( classElements.hasNext() ) {            Element clazz = (Element) classElements.next();                        if(!extendz) {                ClassMapping cmap = new ClassMapping(classPackage, clazz, me, mm);                classMappings.put(cmap.getFullyQualifiedName(),cmap);            } else {                                String ex = clazz.getAttributeValue("extends");                if(ex==null) {                    throw new MappingException("Missing extends attribute on <" + clazz.getName() + " name=" + clazz.getAttributeValue("name") + ">" );                }                ClassMapping superclass = (ClassMapping) classMappings.get(ex);                if(superclass == null) {                    throw new MappingException("Cannot extend unmapped class " + ex);                                    }                ClassMapping subclassMapping = new ClassMapping(classPackage, me, superclass.getClassName(), superclass, clazz, mm);                superclass.addSubClass(subclassMapping);            }        }    }}
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 上古卷轴5东西太多怎么办 上古卷轴天际杀鸡了怎么办 上古卷轴5偷东西被发现怎么办 上古卷轴杀了鸡怎么办 老滚5东西多了怎么办 上古卷轴5被追杀怎么办 全险车自己碰了怎么办 上古卷轴5狗死了怎么办 头发被胶粘住了怎么办 头发被口香糖粘住了怎么办 上古卷轴5杀了npc怎么办 上古卷轴5血太少了怎么办 因牙齿缺失导致变长怎么办 上古卷轴5闪退怎么办? 小米手机4卡顿怎么办 上古卷轴5任务失败怎么办 上古卷轴5爆显存怎么办 老滚5卡住了怎么办 上古卷轴5被木河镇人追杀怎么办 关门的时候有响怎么办 家里门关门太响怎么办 网上赌搏输了2万怎么办 梦见不顺心的事怎么办 振动声桥洗澡时怎么办 同校生2高潮了怎么办 经期血发黑量少怎么办 电脑键盘右边数字键不能用怎么办 御宅伴侣特别卡怎么办 电脑网络出现三角叹号怎么办 同校生2卡顿怎么办 电脑卡了没反应怎么办 促排卵泡多要怎么办 把朋友搞摔倒意外死亡怎么办 猫见到狗受惊了怎么办 头被桌子撞肿了怎么办 鱼缸里的鱼缺氧怎么办 上火眼皮打拉下来怎么办 小孩头敲了个包怎么办 四个月不吃奶怎么办啊 4个月宝宝不吃奶粉怎么办 3个月婴儿不喝奶怎么办