摘自: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 (
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 String name;
private String phone;
private Integer age;
public User() {
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
// 必须重新定义equals()与hashCode()
public boolean equals(Object obj) {
if(obj == this) {
return true;
}
if(!(obj instanceof User)) {
return false;
}
User user = (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>--><?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="onlyfun.caterpillar.User" table="user">
<composite-id>
<key-property name="name"
column="name"
type="java.lang.String"/>
<key-property name="phone"
column="phone"
type="java.lang.String"/>
</composite-id>
<property name="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");
Session session = 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 String name;
private String phone;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public boolean equals(Object obj) {
if(obj == this) {
return true;
}
if(!(obj instanceof User)) {
return false;
}
UserPK pk = (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 UserPK userPK; // 主键
private Integer age;
public User() {
}
public UserPK getUserPK() {
return userPK;
}
public void setUserPK(UserPK userPK) {
this.userPK = userPK;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
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"?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="onlyfun.caterpillar.User" table="user">
<composite-id name="userPK"
class="onlyfun.caterpillar.UserPK"
unsaved-value="any">
<key-property name="name"
column="name"
type="java.lang.String"/>
<key-property name="phone"
column="phone"
type="java.lang.String"/>
</composite-id>
<property name="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");
Session session = sessionFactory.openSession();
// 以主键类实例设定复合主键并加载对应的数据
User user = (User) session.load(User.class, pk);
System.out.println(user.getAge() + "\t" +
user.getUserPK().getName() + "\t" +
user.getUserPK().getPhone());
session.close();
分享到:
相关推荐
《Hibernate复合主键配置与使用详解》 在Java开发中,Hibernate作为一款强大的ORM框架,大大简化了数据库操作。然而,当我们面临复杂的数据表结构,尤其是涉及到复合主键时,如何在Hibernate中进行配置和使用就显得...
在业务代码中,创建和操作复合主键的实体对象与普通实体对象并无太大区别。只需要确保在创建新的`OrderItem`实例时,为其`id`属性提供正确的`OrderItemId`实例即可。 总结,复合主键在Hibernate中是通过`@...
为了使这个复合主键能够正确地参与到数据库的关联操作中,我们还需要创建一个对应的`@TableGenerator`,以便为每个复合主键生成一个唯一的序列号。这通常不是必需的,因为复合主键通常是业务逻辑决定的,而不是自增...
在Hibernate中,对无主键表的操作与普通实体基本相同,只是在保存和查询时需要传入整个复合主键对象。例如,创建一个新的订单: ```java OrderKey key = new OrderKey(); key.setCustomerId("123"); key.setOrderId...
在Hibernate中,通过定义`@Embeddable`的复合主键类和`@EmbeddedId`的实体类,我们可以方便地管理和操作这些复合主键的实体。在保存和查询时,需注意正确设置复合主键的值,以确保数据的正确性。希望这个实例能帮助...
本篇文章将深入探讨Hibernate如何支持和管理复合主键。 一、理解复合主键 在数据库设计中,复合主键是一种特殊情况,当单个字段不能唯一标识表中的每一行时,可以使用两个或多个字段的组合来创建唯一的标识。例如...
### Hibernate复合主键详解 在关系型数据库设计中,经常会出现使用多个字段组合起来作为主键的情况,这种类型的主键被称为复合主键。而在Java领域,尤其是使用Hibernate框架进行持久化操作时,复合主键的应用变得尤...
在Java的Hibernate框架中,复合主键映射是一种处理多列组合成主键的情况,它使得在数据库表中由两个或更多个字段组成的主键能够被正确地映射到实体类。在使用复合主键时,我们需要遵循一定的步骤和规则。 首先,...
这篇文档将介绍如何使用Hibernate注解来生成复合主键或嵌入式主键。 复合主键(Composite Key)是指由两个或更多个列共同构成的唯一标识,而嵌入式主键(Embedded Key)则是将主键字段嵌入到实体类内部。在不使用...
### Hibernate中对数据库复合主键的支持 #### 一、引言 在软件开发过程中,特别是在J2EE领域中,Hibernate作为一种流行的ORM(Object-Relational Mapping)框架被广泛使用。ORM框架的主要作用是将关系型数据库中的...
复合主键关联映射则是处理具有多个字段作为主键的表与对象之间的映射。 通过理解这些知识点,开发者可以更有效地利用Hibernate框架来开发复杂的企业级应用,处理数据持久化以及对象和关系数据库之间的映射。...
本文将详细探讨如何在SSH框架(Spring、Struts、Hibernate)中的实体类使用`@IdClass`注解来定义复合主键,并阐述其使用方法及注意事项。 #### 二、复合主键的定义与应用场景 复合主键是指由两个或两个以上的字段...
**第四部分:Hibernate复合主键** 复合主键在数据库设计中并不罕见,当一个表的主键由两个或更多字段组成时,就需要使用。在Hibernate中,可以使用@EmbeddedId和@IdClass注解来处理复合主键。@EmbeddedId将一个包含...
- 复合主键是自动生成的主键,通过@TableGenerator或@IdClass实现。 **8. 异常处理** - Hibernate提供了自己的异常体系,如HibernateException、ObjectRetrievalFailureException等,需要在编程中适当地捕获和处理...
总结来说,"Hibernate_test"涵盖了Hibernate的基础知识,包括对象关系映射、SessionFactory的创建、集合映射、组件映射以及复合主键的处理。通过学习这些内容,开发者可以更有效地利用Hibernate进行数据库操作,提高...
10. **一对多、多对一、一对一和多对多关系映射**:Hibernate支持多种关联映射,包括集合映射,如List、Set、Map等,以及复合主键的处理。 11. **继承映射**:在Java中,子类可以继承父类。在Hibernate中,这种继承...
Hibernate支持属性映射、类映射、关联映射(一对一、一对多、多对多),以及继承映射和复合主键映射,实现了灵活的数据操作。 5. **Hibernate的使用**:学习Hibernate时,首先需要下载并配置相关库,创建Hibernate...
Hibernate 的基本映射包括 id 算法、复合主键、数据版本并发性控制等。id 算法可以是整型自增、sql server 等数据库的 identity、Oracle 的 sequence、hilo(高低位)算法、uuid、guid、程序赋值等。复合主键可以...
- `@AssociationOverride` 和 `@AttributeOverride`: 在复合主键或嵌套实体中,覆盖默认的关联或属性映射。 **5. 事务处理和缓存** - `@Transactional`: 在服务层方法上标注,启用Spring管理的事务。 - `@Cacheable...