hibernate中使用组件作为标识符
在数据库设计的时候,有时候难免会将主键设置为联合主键(即唯一标识某一实体的属性不止一个).那么在hibernate中将怎么处理组件作为主键呢?
首先创建一个组件类,以Student为例,如果你想将学生的ID和Name作为联合主键,那么你的组件类应该这样写:
1 import java.io.Serializable; 2 3 @SuppressWarnings("serial") 4 //组件类必须实现Serializable接口,并且要重写equals和hashcode方法 5 //重写这两个方法的时候还不能直接使用父类的方法,其逻辑必须与数据中 6 //存储数据的逻辑一致 7 public class StudentPk implements Serializable{ 8 private int id; 9 private String name; 10 11 public int getId() { 12 return id; 13 } 14 public void setId(int id) { 15 this.id = id; 16 } 17 public String getName() { 18 return name; 19 } 20 public void setName(String name) { 21 this.name = name; 22 } 23 24 @Override 25 public boolean equals(Object o){ 26 if(o instanceof StudentPk){ 27 StudentPk pk = (StudentPk)o; 28 if(this.id==pk.getId()&&this.name.equals(pk.getName())){ 29 return true; 30 } 31 } 32 return false; 33 } 34 35 @Override 36 public int hashCode(){ 37 return new StudentPk().hashCode(); 38 } 39 }
其次就是创建你的student类:
1 import com.nenu.hibernate.StudentPk; 2 3 public class Student { 4 private StudentPk pk; 5 private int age; 6 private String phoneNumber; 7 8 public StudentPk getPk() { 9 return pk; 10 } 11 public void setPk(StudentPk pk) { 12 this.pk = pk; 13 } 14 public int getAge() { 15 return age; 16 } 17 public void setAge(int age) { 18 this.age = age; 19 } 20 public String getPhoneNumber() { 21 return phoneNumber; 22 } 23 public void setPhoneNumber(String phoneNumber) { 24 this.phoneNumber = phoneNumber; 25 } 26 }
接下来,如果你要在XML进行配置,那么在Student.hbm.xml文件中就应该这样写:
1 <?xml version="1.0"?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 5 6 <hibernate-mapping package="com.nenu.hibernate"> 7 <class name="Student" table="_student"> 8 <composite-id name="pk" class="com.nenu.hibernate.StudentPk"> 9 <key-property name="id" column="_id"></key-property> 10 <key-property name="name" column="_name"></key-property> 11 </composite-id> 12 13 <property name="age" column="_age"></property> 14 <property name="phoneNumber" column="_phoneNumber"></property> 15 </class> 16 </hibernate-mapping>
之后就是写一个测试类,如下:
1 package com.nenu.hibernate; 2 3 import org.hibernate.Session; 4 import org.hibernate.SessionFactory; 5 import org.hibernate.cfg.Configuration; 6 import com.nenu.hibernate.StudentPk; 7 import com.nenu.hibernate.Student; 8 9 public class StudentTest { 10 public static void main(String[] args) { 11 StudentPk pk = new StudentPk(); 12 pk.setId(1); 13 pk.setName("Dave"); 14 15 Student student = new Student(); 16 student.setPk(pk); 17 student.setAge(15); 18 student.setPhoneNumber("123456789"); 19 20 SessionFactory sf = new Configuration().configure().buildSessionFactory(); 21 Session session = sf.openSession(); 22 session.beginTransaction(); 23 session.save(student); 24 session.getTransaction().commit(); 25 26 session.close(); 27 sf.close(); 28 } 29 }
运行之后;查询数据库就会有如下结果:
如果是使用annotation,那么查阅hibernate--annotation的参考文档就可以知道,annotation提供了三种使用组件作为标识符的注解:
下面就演示第一种方法(另外两种可以参考annotation的参考文档).首先将我的组件类(StudentPk)注解为@Embeddable:
1 package com.nenu.hibernate; 2 3 import java.io.Serializable; 4 5 import javax.persistence.Embeddable; 6 7 @SuppressWarnings("serial") 8 @Embeddable 9 public class StudentPk implements Serializable{ 10 private int id; 11 private String name; 12 13 public int getId() { 14 return id; 15 } 16 public void setId(int id) { 17 this.id = id; 18 } 19 public String getName() { 20 return name; 21 } 22 public void setName(String name) { 23 this.name = name; 24 } 25 26 @Override 27 public boolean equals(Object o){ 28 if(o instanceof StudentPk){ 29 StudentPk pk = (StudentPk)o; 30 if(this.id==pk.getId()&&this.name.equals(pk.getName())){ 31 return true; 32 } 33 } 34 return false; 35 } 36 37 @Override 38 public int hashCode(){ 39 return new StudentPk().hashCode(); 40 } 41 }
然后将组件的属性注解为@id.
1 package com.nenu.hibernate; 2 3 import javax.persistence.Id; 4 5 import com.nenu.hibernate.StudentPk; 6 7 public class Student { 8 private StudentPk pk; 9 private int age; 10 private String phoneNumber; 11 12 @Id 13 public StudentPk getPk() { 14 return pk; 15 } 16 public void setPk(StudentPk pk) { 17 this.pk = pk; 18 } 19 public int getAge() { 20 return age; 21 } 22 public void setAge(int age) { 23 this.age = age; 24 } 25 public String getPhoneNumber() { 26 return phoneNumber; 27 } 28 public void setPhoneNumber(String phoneNumber) { 29 this.phoneNumber = phoneNumber; 30 } 31 }
最后就是创建测试类:
1 import org.hibernate.Session; 2 import org.hibernate.SessionFactory; 3 import org.hibernate.cfg.AnnotationConfiguration; 4 import org.junit.After; 5 import org.junit.AfterClass; 6 import org.junit.Before; 7 import org.junit.BeforeClass; 8 import org.junit.Test; 9 10 import com.nenu.hibernate.Student; 11 import com.nenu.hibernate.StudentPk; 12 13 public class studentTest { 14 public static SessionFactory sf = null; 15 16 @BeforeClass 17 public static void testBefore(){ 18 sf = new AnnotationConfiguration().configure().buildSessionFactory(); 19 } 20 21 @Before 22 public void testBe(){ 23 System.out.println("即将开始测试......"); 24 } 25 26 @Test 27 public void test() { 28 StudentPk pk = new StudentPk(); 29 pk.setId(1); 30 pk.setName("hibernate"); 31 32 Student student = new Student(); 33 student.setPk(pk); 34 student.setAge(22); 35 student.setPhoneNumber("123456789"); 36 37 Session session = sf.openSession(); 38 session.beginTransaction(); 39 session.save(student); 40 session.getTransaction().commit(); 41 session.close(); 42 } 43 44 @After 45 public void testAf(){ 46 System.out.println("测试完毕......"); 47 } 48 @AfterClass 49 public static void testAfter(){ 50 sf.close(); 51 } 52 }
查询数据库;可以看到测试成功:
可以看到,使用annotation的确方便许多.个人更加偏向于使用annotation.
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。