基于业务需求,您会需要使用两个字段来作复合主键,例如在User数据表中,您也许会使用"name"与"phone"两个字段来定义复合主键。
假设您这么建立User表格:
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->
CREATE
TABLE
user
( name
VARCHAR
(
100
)
NOT
NULL
, phone
VARCHAR
(
50
)
NOT
NULL
, age
INT
,
PRIMARY
KEY
(name,phone) );
在表格中,"name"与"age"被定义为复合主键,在映像时,您可以让User类别直接带有"name"与"age"这两个属性,而Hibernate要求复合主键类别要实作Serializable接口,并定义equals()与hashCode()方法:
User.java
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->
package
onlyfun.caterpillar;
import
java.io.Serializable;
import
org.apache.commons.lang.builder.EqualsBuilder;
import
org.apache.commons.lang.builder.HashCodeBuilder;
//
复合主键类的对应类别必须实作Serializable接口
public
class
User
implements
Serializable{
private
Stringname;
private
Stringphone;
private
Integerage;
public
User(){ }
public
IntegergetAge(){
return
age; }
public
void
setAge(Integerage){
this
.age
=
age; }
public
StringgetName(){
return
name; }
public
void
setName(Stringname){
this
.name
=
name; }
public
StringgetPhone(){
return
phone; }
public
void
setPhone(Stringphone){
this
.phone
=
phone; }
//
必须重新定义equals()与hashCode()
public
boolean
equals(Objectobj){
if
(obj
==
this
){
return
true
; }
if
(
!
(obj
instanceof
User)){
return
false
; } Useruser
=
(User)obj;
return
new
EqualsBuilder() .append(
this
.name,user.getName()) .append(
this
.phone,user.getPhone()) .isEquals(); }
public
int
hashCode(){
return
new
HashCodeBuilder() .append(
this
.name) .append(
this
.phone) .toHashCode(); } }
equals()与hashCode()方法被用作两笔不同数据的识别依据;接着您可以使用<composite-id>在映射文件中定义复合主键与对象的属性对应:
User.hbm.xml
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><?xmlversion="1.0"encoding="utf-8"?> <!DOCTYPEhibernate-mapping PUBLIC"-//Hibernate/HibernateMappingDTD3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<classname="onlyfun.caterpillar.User"table="user">
<composite-id>
<key-propertyname="name" column="name" type="java.lang.String"/>
<key-propertyname="phone" column="phone" type="java.lang.String"/>
</composite-id>
<propertyname="age"column="age"type="java.lang.Integer"/>
</class>
</hibernate-mapping>
在储存数据方面,复合主键的储存没什么区别,现在的问题在于如何依据复合主键来查询数据,例如使用load()方法,您可以创建一个User实例,并设定复合主键对应的属性,接着再透过load()查询对应的数据,例如:
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->
Useruser
=
new
User(); user.setName(
"
bush
"
); user.setPhone(
"
0970123456
"
); Sessionsession
=
sessionFactory.openSession();
//
以实例设定复合主键并加载对应的数据
user
=
(User)session.load(User.
class
,user); System.out.println(user.getAge()
+
"
\t
"
+
user.getName()
+
"
\t
"
+
user.getPhone()); session.close();
可以将主键的信息独立为一个类别,例如:
UserPK.java
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->
package
onlyfun.caterpillar;
import
java.io.Serializable;
import
org.apache.commons.lang.builder.EqualsBuilder;
import
org.apache.commons.lang.builder.HashCodeBuilder;
public
class
UserPK
implements
Serializable{
private
Stringname;
private
Stringphone;
public
StringgetName(){
return
name; }
public
void
setName(Stringname){
this
.name
=
name; }
public
StringgetPhone(){
return
phone; }
public
void
setPhone(Stringphone){
this
.phone
=
phone; }
public
boolean
equals(Objectobj){
if
(obj
==
this
){
return
true
; }
if
(
!
(obj
instanceof
User)){
return
false
; } UserPKpk
=
(UserPK)obj;
return
new
EqualsBuilder() .append(
this
.name,pk.getName()) .append(
this
.phone,pk.getPhone()) .isEquals(); }
public
int
hashCode(){
return
new
HashCodeBuilder() .append(
this
.name) .append(
this
.phone) .toHashCode(); } }
现在User类别的主键信息被分离出来了,例如:
User.java
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->
package
onlyfun.caterpillar;
import
java.io.Serializable;
public
class
User
implements
Serializable{
private
UserPKuserPK;
//
主键
private
Integerage;
public
User(){ }
public
UserPKgetUserPK(){
return
userPK; }
public
void
setUserPK(UserPKuserPK){
this
.userPK
=
userPK; }
public
IntegergetAge(){
return
age; }
public
void
setAge(Integerage){
this
.age
=
age; } }
在映像文件方面,需要指定主键类的信息,例如:
User.hbm.xml
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><?xmlversion="1.0"encoding="utf-8"?> <!DOCTYPEhibernate-mapping PUBLIC"-//Hibernate/HibernateMappingDTD3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<classname="onlyfun.caterpillar.User"table="user">
<composite-idname="userPK" class="onlyfun.caterpillar.UserPK" unsaved-value="any">
<key-propertyname="name" column="name" type="java.lang.String"/>
<key-propertyname="phone" column="phone" type="java.lang.String"/>
</composite-id>
<propertyname="age"column="age"type="java.lang.Integer"/>
</class>
</hibernate-mapping>
在查询数据时,必须指定主键信息,例如:
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->
UserPKpk
=
new
UserPK(); pk.setName(
"
bush
"
); pk.setPhone(
"
0970123456
"
); Sessionsession
=
sessionFactory.openSession();
//
以主键类实例设定复合主键并加载对应的数据
Useruser
=
(User)session.load(User.
class
,pk); System.out.println(user.getAge()
+
"
\t
"
+
user.getUserPK().getName()
+
"
\t
"
+
user.getUserPK().getPhone()); session.close();