分享
 
 
 

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

王朝java/jsp·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

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

请先阅读我写的另一篇文章

"使用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.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);

}

}

}

}

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有