请教Hibernate的多主键操作如何实现?

zhengzhiyong 03-07-25

我用的是middlegen的hibernate的plugin,从hibernate的sf网站上下的此插件.
它里面附带一个例子.此例子只能从数据库反向生成*.hbm.xml文件.没有生成持久类文件.
我在build.xml文件用 hbm2java生成java文件.

配置好配置文件,运行ant,出现错误.
1.提示mysql 的schema为null值.
解决:把schema="${database.schema}"
catalog="${database.catalog}"
两行屏蔽掉
2.如果是主表有三个主键,第一个是主表的主键,另外两个是外键,同时也是主键的情况下,在用hbm2java会生成单独的一个主键类,但是生成以后,此主键类没有geter/seter方法.
查明原因,是在生成hbm.xml文件时,<composite-id>的 key-property元素没有指定类型type,所以没有生成主键类相应的geter/seter方法.
解决:在此例子的middlegen-lib目录下有plugin的jar文件,解压缩,在
middlegen.plugins.hibernate包里有个hibernate.vm文件,用ultraedit打开,在68行把<key-property name="${compKeysClass.variableName}"
column="${compKeysClass.sqlName}" />
改为:
<key-property name="${compKeysClass.variableName}"
column="${compKeysClass.sqlName}" type="$column.javaType" />
重新打包为jar文件,放到middlegen-lib目录下.重新编译,就会生成持久类文件.

在此种情况下可以对多主键表进行load,delete,但是不能save和saveOrUpdate操作,执行时抛出
java.lang.ArrayIndexOutOfBoundsException异常:
[java] java.lang.ArrayIndexOutOfBoundsException
[java] at com.mysql.jdbc.PreparedStatement.setInternal(PreparedStatemen
t.java:1955)
[java] at com.mysql.jdbc.PreparedStatement.setInternal(PreparedStatemen
t.java:1977)
[java] at com.mysql.jdbc.PreparedStatement.setInt(PreparedStatement.jav
a:620)
[java] at net.sf.hibernate.type.IntegerType.set(IntegerType.java:27)
[java] at net.sf.hibernate.type.NullableType.nullSafeSet(NullableType.j
ava:46)
[java] at net.sf.hibernate.type.NullableType.nullSafeSet(NullableType.j
ava:31)
[java] at net.sf.hibernate.type.ComponentType.nullSafeSet(ComponentType
.java:163)
[java] at net.sf.hibernate.persister.EntityPersister.dehydrate(EntityPe
rsister.java:373)
[java] at net.sf.hibernate.persister.EntityPersister.insert(EntityPersi
ster.java:472)
[java] at net.sf.hibernate.persister.EntityPersister.insert(EntityPersi
ster.java:450)
[java] at net.sf.hibernate.impl.ScheduledInsertion.execute(ScheduledIns
ertion.java:20)
[java] at net.sf.hibernate.impl.SessionImpl.executeAll(SessionImpl.java
:2101)
[java] at net.sf.hibernate.impl.SessionImpl.execute(SessionImpl.java:20
73)
[java] at net.sf.hibernate.impl.SessionImpl.flush(SessionImpl.java:2017
)
[java] at net.sf.hibernate.transaction.JDBCTransaction.commit(JDBCTrans
action.java:57)
[java] at airline.hibernate.Main.testAddRe(Unknown Source)
[java] at airline.hibernate.Main.<init>(Unknown Source)
[java] at airline.hibernate.Main.main(Unknown Source)
[java] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[java] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAcces
sorImpl.java:39)
[java] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMet
hodAccessorImpl.java:25)
[java] at java.lang.reflect.Method.invoke(Method.java:324)
[java] at org.apache.tools.ant.taskdefs.ExecuteJava.run(ExecuteJava.jav
a:208)
[java] at org.apache.tools.ant.taskdefs.ExecuteJava.execute(ExecuteJava
.java:150)
[java] at org.apache.tools.ant.taskdefs.Java.run(Java.java:443)
[java] at org.apache.tools.ant.taskdefs.Java.executeJava(Java.java:163)

[java] at org.apache.tools.ant.taskdefs.Java.execute(Java.java:108)
[java] at org.apache.tools.ant.Task.perform(Task.java:341)
[java] at org.apache.tools.ant.Target.execute(Target.java:309)
[java] at org.apache.tools.ant.Target.performTasks(Target.java:336)
[java] at org.apache.tools.ant.Project.executeTarget(Project.java:1339)

[java] at org.apache.tools.ant.Project.executeTargets(Project.java:1255
)
[java] at org.apache.tools.ant.Main.runBuild(Main.java:609)
[java] at org.apache.tools.ant.Main.start(Main.java:196)
[java] at org.apache.tools.ant.Main.main(Main.java:235)

不知是我程序写的测试方法有问题,还是hibernate的bug.
希望能给予指导.

但是如果多主键表的另外两个主键没有和其他表关联,一切操作都正常.

下面是我的测试方法:
public void testAddRe() throws HibernateException{
Person person = testLoadPerson(); //Reservation表关联Person表,load出Person对象
Flight flight = testLoadFlight(); //Reservation表关联Flight表,同上
ReservationPK compid = new ReservationPK(); //主键表的主键类
compid.setReservationId(100); //三个主键
compid.setPersonIdFk(200);
compid.setFlightIdFk(100);
Reservation re = new Reservation(); //Reservation表的持久类
re.setComp_id(compid); //set主键类
re.setRegistrationUtc(new java.util.Date()); //其他信息
re.setComment("love yo1");
re.setFlight(flight);
re.setPerson(person);

Session s = sessionFactory.openSession();
Transaction tx = null;
try{
tx = s.beginTransaction();
s.save(re,compid);
tx.commit(); //commit时抛出java.lang.ArrayIndexOutOfBoundsException
}catch(HibernateException he){
if ( tx!=null ){
tx.rollback();
}
throw he;
}finally{
s.close();
}
}

zhengzhiyong
2003-07-26 11:38

大家没有遇到过此种情况吗?麻烦大家了.