一般不提倡用自然主键,而是用代理主键。当无法避免时:look
1 映射单个自然主键
假定在Customer表中没有ID 代理主键,而是以name作为主键。那么Customer类中不必定义id属性,Customer类的OID为name属性。
映射文件为:
<
hibernate-mapping
>
<
class
name
=
"mypack.Customer"
table
=
"customer"
catalog
=
"sampledb"
>
<
id
name
=
"name"
type
=
"java.lang.String"
>
<
column
name
=
"name"
length
=
"20"
/>
<
generator
class
=
"assigned"
/>
</
id
>
<
property
name
=
"age"
type
=
"java.lang.Integer"
>
<
column
name
=
"age"
/>
</
property
>
</
class
>
</
hibernate-mapping
>
没有什么特别的;
2
映射符合自然主键
User
表
name
和
compaby_id
作为复合主键。
<
hibernate-mapping
>
<
class
name
=
"mypack.User"
table
=
"user"
catalog
=
"sampledb"
>
<
composite-id
name
=
"id"
class
=
"mypack.UserId"
>
<
key-property
name
=
"name"
type
=
"java.lang.String"
>
<
column
name
=
"name"
length
=
"20"
/>
</
key-property
>
<
key-property
name
=
"companyId"
type
=
"java.lang.Long"
>
<
column
name
=
"company_id"
/>
</
key-property
>
</
composite-id
>
</
class
>
</
hibernate-mapping
>
UserId
复合主键类
package
mypack;
/**
*
UserId
generated
by
MyEclipse
Persistence
Tools
*/
public
class
UserId
implements
java.io.Serializable {
// Fields
private
String
name
;
private
Long
companyId
;
// Constructors
/**
default
constructor
*/
public
UserId() {
}
/**
full
constructor
*/
public
UserId(String name, Long companyId) {
this
.
name
= name;
this
.
companyId
= companyId;
}
// Property accessors
public
String getName() {
return
this
.
name
;
}
public
void
setName(String name) {
this
.
name
= name;
}
public
Long getCompanyId() {
return
this
.
companyId
;
}
public
void
setCompanyId(Long companyId) {
this
.
companyId
= companyId;
}
public
boolean
equals(Object other) {
if
((
this
== other))
return
true
;
if
((other ==
null
))
return
false
;
if
(!(other
instanceof
UserId))
return
false
;
UserId castOther = (UserId) other;
return
((
this
.getName() == castOther.getName()) || (
this
.getName() !=
null
&& castOther.getName() !=
null
&&
this
.getName().equals(
castOther.getName())))
&& ((
this
.getCompanyId() == castOther.getCompanyId()) || (
this
.getCompanyId() !=
null
&& castOther.getCompanyId() !=
null
&&
this
.getCompanyId().equals(castOther.getCompanyId())));
}
public
int
hashCode() {
int
result = 17;
result = 37 * result
+ (getName() ==
null
? 0 :
this
.getName().hashCode());
result = 37 * result
+ (getCompanyId() ==
null
? 0 :
this
.getCompanyId().hashCode());
return
result;
}
}
User
类:
package
mypack;
/**
*
User
generated
by
MyEclipse
Persistence
Tools
*/
public
class
User
implements
java.io.Serializable {
// Fields
private
UserId
id
;
// Constructors
/**
default
constructor
*/
public
User() {
}
/**
full
constructor
*/
public
User(UserId id) {
this
.
id
= id;
}
// Property accessors
public
UserId getId() {
return
this
.
id
;
}
public
void
setId(UserId id) {
this
.
id
= id;
}
}
小结:
1
书上在映射自然主键时,在映射文件中加入了
<version name=”version” column=”VERSION” unsaved-value=”0” />
是为了区分
Customer
对象的状态,是临时态的还是游离态的。因为书中使用了
session
的
saveOrupdate ()
方法,此方法根据对象的状态来决定是保存对象还是更新对象。如果我们把
save
和
update
方法分开来用就不需要上面定义的
version
属性了。
2
映射复合主键时,要重写对应类的
equals
方法和
hashcode
方法。
3
映射复合自然主键时,
在映射文件中可以直接写复合主键:
<composite-id >
<key-property name="name" type="java.lang.String">
<column name="name" length="20" />
</key-property>
<key-property name="companyId" type="java.lang.Long">
<column name="company_id" />
</key-property>
</composite-id>
也可以把复合主键单独写成一个类:
UserId
在
User
类中把
UserId
作为属性
<composite-id name="id" class="mypack.UserId">
<key-property name="name" type="java.lang.String">
<column name="name" length="20" />
</key-property>
<key-property name="companyId" type="java.lang.Long">
<column name="company_id" />
</key-property>
</composite-id>