復合主鍵,由多個字段組成主鍵,例如,使用一個用戶的firstname和lastname組成主鍵。
可以通過兩種方式確定主鍵,一種是基于實體類的復合主鍵,另一種是通過定義主鍵類來實現。
不管通過哪種方式,復合主鍵都需要實現equals方法和hashcode方法,以作為不同數據之間是別的標志。
一.基于實體類屬性的復合主鍵
主鍵由實體類中的屬性組成。
1.映射文件TUser.hbm.xml
xml 代碼
- <? xml ? version = "1.0" ?> ??
- <!DOCTYPE?hibernate-mapping?PUBLIC?"-//Hibernate/Hibernate?Mapping?DTD?3.0//EN" ??
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" > ??
- < hibernate-mapping > ??
- ???? < class ? name = "cn.blogjava.start.TUser" ? table = "t_user" ? catalog = "sample" > ??
- ???????? < composite-id > ??
- ???????????? < key-property ? name = "lastname" ? column = "lastname" ? type = "string" ? /> ??
- ???????????? < key-property ? name = "firstname" ? column = "firstname" ? type = "string" ? /> ??
- ???????? </ composite-id > ??
- ??
- ???????? < property ? name = "age" ? type = "integer" ? column = "age" /> ??
- ???? </ class > ??
- </ hibernate-mapping > ??
2.TUser.java
java 代碼
- package ?cn.blogjava.start; ??
- ??
- import ?org.apache.commons.lang.builder.EqualsBuilder; ??
- import ?org.apache.commons.lang.builder.HashCodeBuilder; ??
- ??
- /** ?
- ?*?TUser?generated?by?hbm2java ?
- ?*/ ??
- ??
- public ? class ?TUser? implements ?java.io.Serializable?{ ??
- ??
- ???? //?Fields???? ??
- ??
- ???? private ?Integer?age; ??
- ??
- ???? private ?String?firstname; ??
- ??
- ???? private ?String?lastname; ??
- ??
- ???? public ?Integer?getAge()?{ ??
- ???????? return ?age; ??
- ????} ??
- ??
- ???? public ? void ?setAge(Integer?age)?{ ??
- ???????? this .age?=?age; ??
- ????} ??
- ??
- ???? public ?String?getFirstname()?{ ??
- ???????? return ?firstname; ??
- ????} ??
- ??
- ???? public ? void ?setFirstname(String?firstname)?{ ??
- ???????? this .firstname?=?firstname; ??
- ????} ??
- ??
- ???? public ?String?getLastname()?{ ??
- ???????? return ?lastname; ??
- ????} ??
- ??
- ???? public ? void ?setLastname(String?lastname)?{ ??
- ???????? this .lastname?=?lastname; ??
- ????} ??
- ???? ??
- ???? public ? boolean ?equals(Object?obj)?{ ??
- ???????? if (!(obj? instanceof ?TUser))?{ ??
- ???????????? return ? false ; ??
- ????????} ??
- ???????? ??
- ????????TUser?user?=?(TUser)obj; ??
- ???????? return ? new ?EqualsBuilder()?????????? //?EqualsBuilder?和HashCodeBuilder均為apache?common?lang包中的工具類 ??
- ????????????.appendSuper( super .equals(obj)) ??
- ????????????.append( this .lastname,?user.lastname) ??
- ????????????.append( this .firstname,?user.firstname) ??
- ????????????.isEquals();???????? ??
- ????} ??
- ???? ??
- ???? public ? int ?hasCode()?{ ??
- ???????? return ? new ?HashCodeBuilder(- 528253723 ,?- 475504089 ) ??
- ????????????.appendSuper( super .hashCode()) ??
- ????????????.append( this .lastname).append( this .firstname) ??
- ????????????.toHashCode(); ??
- ???????????? ??
- ????} ??
- ??
- }??
3.測試類HibernateTest.java
java 代碼
- package ?cn.blogjava.start; ??
- ??
- import ?junit.framework.Assert; ??
- import ?junit.framework.TestCase; ??
- ??
- import ?org.hibernate.HibernateException; ??
- import ?org.hibernate.Session; ??
- import ?org.hibernate.SessionFactory; ??
- import ?org.hibernate.Transaction; ??
- import ?org.hibernate.cfg.Configuration; ??
- ??
- ??
- public ? class ?HibernateTest? extends ?TestCase?{ ??
- ???? ??
- ????Session?session?=? null ; ??
- ???? /** ?
- ?????*?JUnit中的setUp方法在TestCase初始化的時候會自動調用 ?
- ?????*?一般用于初始化公用資源 ?
- ?????*/ ??
- ???? protected ? void ?setUp()?{ ??
- ???????? try ?{ ??
- ???????????? /** ?
- ?????????????*?可以采用hibernate.properties或者hibernate.cfg.xml ?
- ?????????????*?配置文件的初始化代碼 ?
- ?????????????*? ?
- ?????????????*?采用hibernate.properties ?
- ?????????????*?Configuration?config?=?new?Configuration(); ?
- ?????????????*?config.addClass(TUser.class); ?
- ?????????????*/ ??
- ???????????? ??
- ???????????? //采用hibernate.cfg.xml配置文件,與上面的方法對比,兩個差異 ??
- ???????????? //1.Configuration的初始化方式 ??
- ???????????? //2.xml ??
- ????????????Configuration?config?=? new ?Configuration().configure(); ??
- ????????????SessionFactory?sessionFactory?=?config.buildSessionFactory(); ??
- ????????????session?=?sessionFactory.openSession(); ??
- ???????????? ??
- ????????}? catch ?(HibernateException?e)?{ ??
- ???????????? //?TODO:?handle?exception ??
- ????????????e.printStackTrace(); ??
- ????????}???????? ??
- ????} ??
- ??
- ???? /** ?
- ?????*?JUnit中的tearDown方法在TestCase執行完畢的時候會自動調用 ?
- ?????*?一般用于釋放資源 ?
- ?????*/ ???? ??
- ???? protected ? void ?tearDown()?{ ??
- ???????? try ?{ ??
- ????????????session.close();???????? ??
- ????????}? catch ?(HibernateException?e)?{ ??
- ???????????? //?TODO:?handle?exception ??
- ????????????e.printStackTrace(); ??
- ????????}???????? ??
- ????}???? ??
- ???? ??
- ???? /** ?
- ?????*?對象持久化測試(Insert方法) ?
- ?????*/ ???????? ??
- ???? public ? void ?testInsert()?{ ??
- ????????Transaction?tran?=? null ; ??
- ???????? try ?{ ??
- ????????????tran?=?session.beginTransaction(); ??
- ????????????TUser?user?=? new ?TUser(); ??
- ????????????user.setFirstname( "bai" ); ??
- ????????????user.setLastname( "yunfeng" ); ??
- ????????????user.setAge( 26 ); ??
- ????????????session.save(user); ??
- ????????????session.flush(); ??
- ????????????tran.commit(); ??
- ????????}? catch ?(HibernateException?e)?{ ??
- ???????????? //?TODO:?handle?exception ??
- ????????????e.printStackTrace(); ??
- ????????????Assert.fail(e.getMessage()); ??
- ???????????? if (tran?!=? null )?{ ??
- ???????????????? try ?{ ??
- ????????????????????tran.rollback(); ??
- ????????????????}? catch ?(Exception?e1)?{ ??
- ???????????????????? //?TODO:?handle?exception ??
- ????????????????????e1.printStackTrace(); ??
- ????????????????} ??
- ????????????} ??
- ????????} ??
- ????} ??
- ???? ??
- ???? /** ?
- ?????*?對象讀取測試(Select方法) ?
- ?????*/ ???????????? ??
- ???? public ? void ?testSelect(){ ??
- ????????TUser?user?=? new ?TUser(); ??
- ????????user.setFirstname( "bai" ); ??
- ????????user.setLastname( "yunfeng" ); ??
- ???????? ??
- ????????user?=?(TUser)session.load(TUser. class ,?user); ??
- ????????Assert.assertEquals(user.getAge().intValue(),? 26 ); ??
- ????} ??
- } ??
基于主鍵類的復合主鍵:
方法:將主鍵字段從POJO類中提出了,生成一個主鍵類。
可以將1中的例子加以改造,將firstname和lastname字段單獨提取到一個主鍵類中。
1.
配置文件TUser.hbm.xml
composite-id節點的name指定了實體類中的主鍵類的屬性名.
xml 代碼
- <? xml ? version = "1.0" ?> ??
- <!DOCTYPE?hibernate-mapping?PUBLIC?"-//Hibernate/Hibernate?Mapping?DTD?3.0//EN" ??
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" > ??
- < hibernate-mapping ? package = "cn.blogjava.start" > ??
- ???? < class ? name = "TUser" ? table = "t_user" ? catalog = "sample" > ??
- ???????? < composite-id ? name = "userPK" ? class = "TUserPK" > ??
- ???????????? < key-property ? name = "lastname" ? column = "lastname" ? type = "string" ? /> ??
- ???????????? < key-property ? name = "firstname" ? column = "firstname" ? type = "string" ? /> ??
- ???????? </ composite-id > ??
- ??
- ???????? < property ? name = "age" ? type = "integer" ? column = "age" /> ??
- ???? </ class > ??
- </ hibernate-mapping > ??
2.POJO類
- package ?cn.blogjava.start; ??
- ??
- /** ?
- ?*?TUser?generated?by?hbm2java ?
- ?*/ ??
- ??
- public ? class ?TUser? implements ?java.io.Serializable?{ ??
- ??
- ???? //?Fields???? ??
- ??
- ???? private ?Integer?age; ??
- ???? ??
- ???? //配置文件composite-id的name屬性 ??
- ???? private ?TUserPK?userPK; ??
- ??
- ??
- ???? public ?Integer?getAge()?{ ??
- ???????? return ?age; ??
- ????} ??
- ??
- ???? public ? void ?setAge(Integer?age)?{ ??
- ???????? this .age?=?age; ??
- ????} ??
- ??
- ???? public ?TUserPK?getUserPK()?{ ??
- ???????? return ?userPK; ??
- ????} ??
- ??
- ???? public ? void ?setUserPK(TUserPK?userPK)?{ ??
- ???????? this .userPK?=?userPK; ??
- ????} ??
- }??
3.主鍵類TUserPK.java
java 代碼
- package ?cn.blogjava.start; ??
- ??
- import ?java.io.Serializable; ??
- ??
- import ?org.apache.commons.lang.builder.EqualsBuilder; ??
- import ?org.apache.commons.lang.builder.HashCodeBuilder; ??
- ??
- public ? class ?TUserPK? implements ?Serializable?{ ??
- ??
- ???? private ?String?firstname; ??
- ???? private ?String?lastname; ??
- ??
- ???? public ?String?getFirstname()?{ ??
- ???????? return ?firstname; ??
- ????} ??
- ??
- ???? public ? void ?setFirstname(String?firstname)?{ ??
- ???????? this .firstname?=?firstname; ??
- ????} ??
- ??
- ???? public ?String?getLastname()?{ ??
- ???????? return ?lastname; ??
- ????} ??
- ??
- ???? public ? void ?setLastname(String?lastname)?{ ??
- ???????? this .lastname?=?lastname; ??
- ????} ??
- ???? ??
- ???? public ? boolean ?equals(Object?obj)?{ ??
- ???????? if (!(obj? instanceof ?TUserPK))?{ ??
- ???????????? return ? false ; ??
- ????????} ??
- ???????? ??
- ????????TUserPK?userPK?=?(TUserPK)obj; ??
- ???????? return ? new ?EqualsBuilder() ??
- ????????????.appendSuper( super .equals(obj)) ??
- ????????????.append( this .lastname,?userPK.lastname) ??
- ????????????.append( this .firstname,?userPK.firstname) ??
- ????????????.isEquals();???????? ??
- ????} ??
- ???? ??
- ???? public ? int ?hasCode()?{ ??
- ???????? return ? new ?HashCodeBuilder(- 528253723 ,?- 475504089 ) ??
- ????????????.appendSuper( super .hashCode()) ??
- ????????????.append( this .lastname).append( this .firstname) ??
- ????????????.toHashCode();???????????? ??
- ????} ??
- } ??
4.測試代碼HibernateTest.java
java 代碼
- package ?cn.blogjava.start; ??
- ??
- import ?junit.framework.Assert; ??
- import ?junit.framework.TestCase; ??
- ??
- import ?org.hibernate.HibernateException; ??
- import ?org.hibernate.Session; ??
- import ?org.hibernate.SessionFactory; ??
- import ?org.hibernate.Transaction; ??
- import ?org.hibernate.cfg.Configuration; ??
- ??
- ??
- public ? class ?HibernateTest? extends ?TestCase?{ ??
- ???? ??
- ????Session?session?=? null ; ??
- ???? /** ?
- ?????*?JUnit中的setUp方法在TestCase初始化的時候會自動調用 ?
- ?????*?一般用于初始化公用資源 ?
- ?????*/ ??
- ???? protected ? void ?setUp()?{ ??
- ???????? try ?{ ??
- ???????????? /** ?
- ?????????????*?可以采用hibernate.properties或者hibernate.cfg.xml ?
- ?????????????*?配置文件的初始化代碼 ?
- ?????????????*? ?
- ?????????????*?采用hibernate.properties ?
- ?????????????*?Configuration?config?=?new?Configuration(); ?
- ?????????????*?config.addClass(TUser.class); ?
- ?????????????*/ ??
- ???????????? ??
- ???????????? //采用hibernate.cfg.xml配置文件,與上面的方法對比,兩個差異 ??
- ???????????? //1.Configuration的初始化方式 ??
- ???????????? //2.xml ??
- ????????????Configuration?config?=? new ?Configuration().configure(); ??
- ????????????SessionFactory?sessionFactory?=?config.buildSessionFactory(); ??
- ????????????session?=?sessionFactory.openSession(); ??
- ???????????? ??
- ????????}? catch ?(HibernateException?e)?{ ??
- ???????????? //?TODO:?handle?exception ??
- ????????????e.printStackTrace(); ??
- ????????}???????? ??
- ????} ??
- ??
- ???? /** ?
- ?????*?JUnit中的tearDown方法在TestCase執行完畢的時候會自動調用 ?
- ?????*?一般用于釋放資源 ?
- ?????*/ ???? ??
- ???? protected ? void ?tearDown()?{ ??
- ???????? try ?{ ??
- ????????????session.close();???????? ??
- ????????}? catch ?(HibernateException?e)?{ ??
- ???????????? //?TODO:?handle?exception ??
- ????????????e.printStackTrace(); ??
- ????????}???????? ??
- ????}???? ??
- ???? ??
- ???? /** ?
- ?????*?對象持久化測試(Insert方法) ?
- ?????*/ ???????? ??
- ???? public ? void ?testInsert()?{ ??
- ????????Transaction?tran?=? null ; ??
- ???????? try ?{ ??
- ????????????tran?=?session.beginTransaction(); ??
- ????????????TUser?user?=? new ?TUser(); ??
- ????????????TUserPK?userPK?=? new ?TUserPK(); ??
- ????????????userPK.setFirstname( "yu" ); ??
- ????????????userPK.setLastname( "yy" ); ??
- ????????????user.setUserPK(userPK); ??
- ????????????user.setAge( 25 ); ??
- ????????????session.save(user); ??
- ????????????session.flush(); ??
- ????????????tran.commit(); ??
- ????????}? catch ?(HibernateException?e)?{ ??
- ???????????? //?TODO:?handle?exception ??
- ????????????e.printStackTrace(); ??
- ????????????Assert.fail(e.getMessage()); ??
- ???????????? if (tran?!=? null )?{ ??
- ???????????????? try ?{ ??
- ????????????????????tran.rollback(); ??
- ????????????????}? catch ?(Exception?e1)?{ ??
- ???????????????????? //?TODO:?handle?exception ??
- ????????????????????e1.printStackTrace(); ??
- ????????????????} ??
- ????????????} ??
- ????????} ??
- ????} ??
- ???? ??
- ???? /** ?
- ?????*?對象讀取測試(Select方法) ?
- ?????*/ ???????????? ??
- ???? public ? void ?testSelect(){ ??
- ????????TUserPK?userPK?=? new ?TUserPK(); ??
- ????????userPK.setFirstname( "yu" ); ??
- ????????userPK.setLastname( "yy" ); ??
- ???????? ??
- ????????TUser?user?=?(TUser)session.load(TUser. class ,?userPK); ??
- ????????Assert.assertEquals(user.getAge().intValue(),? 25 ); ??
- ????} ??
- } ??