之前写了id的生成策略,但有时候我们的数据库表的主键并不是唯一的一个属性,这就要用到联合主键,配置方法呢同样有两个,xml和annotation。当然我们在设计数据库表的时候尽量不要去这么设计,但是要是遇到了这种情况,要学会配置。
还是先来看项目
对于Student,我们认为age和id作为联合主键,那么新建一个Student_pk.java里面有age 和int 属性还有get方法。
package com.tfj.hibernate; import java.io.Serializable; public class Student_pk implements Serializable{ private int id; private int age; public int getId() { return id; } public int getAge() { return age; } public void setId(int id) { this.id = id; } public void setAge(int age) { this.age = age; } @Override public int hashCode() { return super.hashCode(); } @Override public boolean equals(Object obj) { if(obj instanceof Student_pk){ Student_pk pk= (Student_pk)obj; if(this.id==pk.getId()&&this.age==pk.getAge()){ return true; } } return false; } }
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.tfj.hibernate.Student" table="student"> <composite-id name="pk" class="com.tfj.hibernate.Student_pk"> <key-property name="age"></key-property> <key-property name="id"></key-property> </composite-id> <property name="name"></property> <property name="sex"></property> <property name="good"></property> </class> </hibernate-mapping>
@Test public void testTeacherSave() { Teacher t = new Teacher(); Teacher_pk pk = new Teacher_pk(); pk.setId(5); pk.setName("hello"); t.setPk(pk); t.setTitle("高级"); t.setYourWifeName("春娇"); t.setBirthDate(new Date()); Session session = sessionFactory.getCurrentSession(); session.beginTransaction(); session.save(t); session.getTransaction().commit(); }
还要实现equal()和hashcode()方法。
equal()方法当id和age都一样的时候就是相同的。
下面说annotation
annotation要实现这个有3种方法,我看的文档没有给出翻译。(现在我们用Teacher和Teacher_pk来说)是这样如下三种
1)把主键类(Teacher_pk)注册为@ Embeddable,把主键属性(在Teacher里的pk)注册为@Id;
2)把组件的属性注册为@EmbeddeId;
3)把类注解为@IdClass把属于主键的属性注解为@Id;
对于第三种和第二种用的多,关于为什么要有@IdClass,虽然我们在存的时候没有用到这个类,但是在读取的时候还是会用到,所以这个类应该存在。