hibernate复合主键的操作

 摘自:http://www.blogjava.net/alex/archive/2006/11/09/80231.html

基于业务需求,您会需要使用两个字段来作复合主键,例如在User数据表中,您也许会使用"name"与"phone"两个字段来定义复合主键。

假设您这么建立User表格:

<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->CREATE TABLE user (

nameVARCHAR(100)NOTNULL,

phoneVARCHAR(50)NOTNULL,

ageINT,

PRIMARYKEY(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;

importjava.io.Serializable;

importorg.apache.commons.lang.builder.EqualsBuilder;

importorg.apache.commons.lang.builder.HashCodeBuilder;

//复合主键类的对应类别必须实作Serializable接口

publicclassUserimplementsSerializable{

privateStringname;

privateStringphone;

privateIntegerage;

publicUser(){

}

publicIntegergetAge(){

returnage;

}

publicvoidsetAge(Integerage){

this.age=age;

}

publicStringgetName(){

returnname;

}

publicvoidsetName(Stringname){

this.name=name;

}

publicStringgetPhone(){

returnphone;

}

publicvoidsetPhone(Stringphone){

this.phone=phone;

}

//必须重新定义equals()与hashCode()

publicbooleanequals(Objectobj){

if(obj==this){

returntrue;

}

if(!(objinstanceofUser)){

returnfalse;

}

Useruser=(User)obj;

returnnewEqualsBuilder()

.append(this.name,user.getName())

.append(this.phone,user.getPhone())

.isEquals();

}

publicinthashCode(){

returnnewHashCodeBuilder()

.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>--><?xml version="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>-->User user = 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;

importjava.io.Serializable;

importorg.apache.commons.lang.builder.EqualsBuilder;

importorg.apache.commons.lang.builder.HashCodeBuilder;

publicclassUserPKimplementsSerializable{

privateStringname;

privateStringphone;

publicStringgetName(){

returnname;

}

publicvoidsetName(Stringname){

this.name=name;

}

publicStringgetPhone(){

returnphone;

}

publicvoidsetPhone(Stringphone){

this.phone=phone;

}

publicbooleanequals(Objectobj){

if(obj==this){

returntrue;

}

if(!(objinstanceofUser)){

returnfalse;

}

UserPKpk=(UserPK)obj;

returnnewEqualsBuilder()

.append(this.name,pk.getName())

.append(this.phone,pk.getPhone())

.isEquals();

}

publicinthashCode(){

returnnewHashCodeBuilder()

.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;

importjava.io.Serializable;

publicclassUserimplementsSerializable{

privateUserPKuserPK;//主键

privateIntegerage;

publicUser(){

}

publicUserPKgetUserPK(){

returnuserPK;

}

publicvoidsetUserPK(UserPKuserPK){

this.userPK=userPK;

}

publicIntegergetAge(){

returnage;

}

publicvoidsetAge(Integerage){

this.age=age;

}

}

 

在映像文件方面,需要指定主键类的信息,例如:

User.hbm.xml

<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><?xml version="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>-->UserPK pk = 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();

相关推荐