在实际开发中我们有时并不是使用一个字段当主键,有时也会使用2个以及以上字段当作主键,这种情况在hibernate中怎么实现那,hibernate给我们提供了2种方式实现,主键类实现和非主键类实现;
我们都用Customers 这个类中的cardId 和name做主键来讲解
非主键类实现
实体类
public class Customers implements java.io.Serializable {
// Fields
private String cardId;
private String name;
private String address;
映射文件
<hibernate-mapping>
<class name="com.wfg.Customers" table="customers" catalog="ontomany">
<composite-id >
<key-property name="cardId" column="card_id" type="string"></key-property>
<key-property name="name" column="_name" type="string"></key-property>
</composite-id>
<property name="address" type="java.lang.String">
<column name="address_" length="15" />
</property>
</class>
</hibernate-mapping>
使用Schema创建表结构输出语句
drop table if exists ontomany.customers
create table ontomany.customers (card_id varchar(255) not null, _name varchar(255) not null, address_ varchar(15), primary key (card_id, _name))
测试代码:
Customers cus = new Customers();
//cus.setAddress("shanghai");
cus.setCardId("1000");
cus.setName("张三");
cus.setAddress("shanghai");
//session.save(cus);
Customers cus1 = new Customers();
cus1.setName("张三");
cus1.setCardId("1000");
Customers cus2 = (Customers)session.get(Customers.class,cus1 );
System.out.println(cus1.getAddress());
System.out.println(cus2.getAddress());
打印的结果都为shanghai.证明从数据库中查询出数据了
主键类实现
我们接着来讲主键类实现方式
Customers 主键类
public class CustomersPermaryKey implements Serializable{
private String cardId;
private String name;
public String getCardId() {
return cardId;
}
public void setCardId(String cardId) {
this.cardId = cardId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((cardId == null) ? 0 : cardId.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
CustomersPermaryKey other = (CustomersPermaryKey) obj;
if (cardId == null) {
if (other.cardId != null)
return false;
} else if (!cardId.equals(other.cardId))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
Customers 类
public class Customers {
// Fields
private CustomersPermaryKey customersPermaryKey;
private String address;
映射文件:
<hibernate-mapping>
<class name="com.wfg.Customers" table="customers" catalog="ontomany">
<composite-id name="customersPermaryKey" class="com.wfg2.CustomersPermaryKey" >
<key-property name="cardId" column="card_id" type="string"></key-property>
<key-property name="name" column="_name" type="string"></key-property>
</composite-id>
<property name="address" type="java.lang.String">
<column name="address_" length="15" />
</property>
</class>
</hibernate-mapping>
这里和非主键类实现方式仅仅是在 composite-id 标签中加了下面2个属性:name=”customersPermaryKey” class=”com.wfg2.CustomersPermaryKey” >
使用Schema创建表结构输出语句
drop table if exists ontomany.customers
create table ontomany.customers (card_id varchar(255) not null, _name varchar(255) not null, address_ varchar(15), primary key (card_id, _name))
这里和非主键类实现方式一模一样的表结构
测试代码
CustomersPermaryKey key = new CustomersPermaryKey();
key.setCardId("1000");
key.setName("lisi");
Customers cus = new Customers();
cus.setCustomersPermaryKey(key);
cus.setAddress("shanghai");
session.save(cus);
总结:其实这2种实现方式不一样但是底层是一样的原理;
1) 类中的每个主键属性都对应到数据表中的每个主键列。
Hibernate要求具有联合主键的实体类实现 Serializable接口,并且重写 hashCode 与 equals 方法,重写这两个方法的原因在于Hibernate 要根据数据库的联合主键来判断某两行记录是否是一样的,如果一样那么就认为是同一个对象,如果不一样,那么就认为是不同的对象。这反映到程序领域中就是根据hashCode 与 equals 方法来判断某两个对象是否能够放到诸如Set 这样的集合当中。联合主键的实体类实现 Serializable 接口的原因在于使用get或load方法的时候需要先构建出来该实体的对象,并且将查询依据(联合主键)设置进去,然后作为 get或 load方法的第二个参数传进去即可。
2) 将主键所对应属性提取出一个类(称之为主键类) ,并且主键类
需要实现Serializable接口,重写equals方法与hashCode方法,原因与上面一样。
源码:
链接:http://pan.baidu.com/s/1boNXpfT 密码:054t