bug? Hbm2JavaTask無法實現joined-subclass單獨設定檔(2.1.2)

來源:互聯網
上載者:User

如果你並不打算使用類繼承結構並不是很有必要閱讀本文。請先閱讀我寫的另一篇文章 "使用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 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); } } }}


相關文章

Beyond APAC's No.1 Cloud

19.6% IaaS Market Share in Asia Pacific - Gartner IT Service report, 2018

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。