請教Hibernate的多主鍵操作如何實現?

zhengzhiyong發表於2003-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();
}
}

相關文章