來講個經驗吧!!
因為案子要處理一些老舊的資料, 我必須要使用Hibernate從資料庫中取得資料。我有2張table:DEMO_LOG與DEMO_JOB。 DEMO_LOG的JOBID與JOB_TYPE會參數到DEMO_JOB的JOB_ID與JOB_TYPE欄位。
資料的Schema如下:
create table DEMO_LOG(
LOGID INTEGER,
JOBID VARCHAR2(10),
JOB_TYPE VARCHAR2(4),
....
)
create table DEMO_JOB(
JOB_ID VARCHAR2(10),
JOB_TYPE VARCHAR2(4),
...
)
請注意:DEMO_LOG.JOBID欄位沒有底線,DEMO_JOB.JOB_ID是有底線的。為什麼會這樣呢?? 因為我在建schema時打錯了...:p。不過這無傷大雅。重點來了,2張table的primary-key如下:
primary key ()
沒錯,它沒有promary-key。
不過依照table的用途,我認為在DEMO_LOG這張table中,JOBID+JOB_TYPE是unique的;而DEMO_JOB中JOB_ID與JOB_TYPE也是unique的。於是我的hbm是這樣寫:
<hibernate-mapping>
<class name="dao.DemoLog" table="DEMO_LOG">
<composite-id name="id" class="dao.DemoLogId">
<key-property name="jobid" type="java.lang.String">
<column name="JOBID" length="10" />
</key-property>
<key-property name="jobType" type="java.lang.String">
<column name="JOB_TYPE" length="4" />
</key-property>
<key-property name="logid" type="java.lang.Long">
<column name="LOGID" precision="22" scale="0" />
</key-property>
</composite-id>
<many-to-one name="jobinfo" class="dao.DemoJob"
outer-join="true" insert="false" update="false"
unique="false" property-ref="jobpk" not-null="false">
<column name="JOBID" />
<column name="JOB_TYPE" />
</many-to-one>
.....
</hibernate-mapping>
<hibernate-mapping>
<class name="dao.DemoJob" table="DEMO_JOB">
<composite-id name="id" class="dao.DemoJobId">
<key-property name="jobId" type="java.lang.String">
<column name="JOB_ID" length="10" />
</key-property>
<key-property name="jobType" type="java.lang.String">
<column name="JOB_TYPE" length="4" />
</key-property>
</composite-id>
<properties name="jobpk">
<property name="jobId" type="java.lang.String"
insert="false" update="false">
<column name="JOB_ID" length="10" />
</property>
<property name="jobType" type="java.lang.String"
insert="false" update="false">
<column name="JOB_TYPE" length="4" />
</property>
</properties>
</hibernate-mapping>
它所產生出來的SQL語法如下:
select this_.JOBID as JOBID2_1_, this_.JOB_TYPE as JOB2_2_1_,
this_.LOGID as LOGID2_1_,
.....
demojob2_.JOB_ID as JOB1_1_0_,
demojob2_.JOB_TYPE as JOB2_1_0_
from DEMO_LOG this_
left outer join DEMO_JOB demojob2_ on this_.JOBID =
demojob2_.JOB_ID
and this_.JOB_TYPE =
demojob2_.JOB_TYPE;
select demojob0_.JOB_ID as JOB1_1_0_,
demojob0_.JOB_TYPE as JOB2_1_0_,
.....
from DEMO_JOB demojob0_
where demojob0_.JOB_ID = ?
and demojob0_.JOB_TYPE = ?
當然,依照Hibernate說明文件, DemoLogId中的equals與hashCode method也都實作了。 有一些要注意的。
- 無論是DEMO_LOG或DEMO_JOB,在hbm中被定義為primary key的欄位其值不可以為null。 不然取得的list中雖然會有這個element,可是Object卻會是null。想要解決這個問題嗎??可以參考這篇文章。
- 因為在實際table中是無primary ky的,所以資料是可以重覆。但是在hibernate中的entity,則會與select出來的第一筆記錄有相同的instance。
- 重點在於如果DEMO_JOB中有對應不到的記錄,DEMO_LOG所代表的entity還是會呈現,只是差別在於jobinfo property為null。這正是我要處理的...。X的,什麼鳥系統設計的鳥schema....。
下一步:要怎麼處理primary-key property重覆的問題了。