复合主键在表中有多个属性共同确定一个元素,对应到实体类中就有多个属性共同构成主键属性。可以把主键属性分离出来单独成一个类,也可以不分离。
如果不分离,那实体类也是主键类,关键点是主键类要实现Serializable接口,并且重写hashCode和equals方法。
下面的例子是将复合主键分离出来单独成一个类:
StudentKey.java:
1 /** 2 * 包含学生表格主键对应的属性,主键类 3 * 4 * @author hanyuan 5 * @time 2012-8-23 下午09:21:51 6 */ 7 public class StudentKey implements Serializable { 8 // 学生学号 9 private long studentId; 10 // 学生姓名 11 private String name; 12 13 public long getStudentId() { 14 return studentId; 15 } 16 17 public void setStudentId(long studentId) { 18 this.studentId = studentId; 19 } 20 21 public String getName() { 22 return name; 23 } 24 25 public void setName(String name) { 26 this.name = name; 27 } 28 29 //重写hashCode和equals方法 30 @Override 31 public int hashCode() { 32 final int prime = 31; 33 int result = 1; 34 result = prime * result + ((name == null) ? 0 : name.hashCode()); 35 result = prime * result + (int) (studentId ^ (studentId >>> 32)); 36 return result; 37 } 38 39 @Override 40 public boolean equals(Object obj) { 41 if (this == obj) 42 return true; 43 if (obj == null) 44 return false; 45 if (getClass() != obj.getClass()) 46 return false; 47 StudentKey other = (StudentKey) obj; 48 if (name == null) { 49 if (other.name != null) 50 return false; 51 } 52 else if (!name.equals(other.name)) 53 return false; 54 if (studentId != other.studentId) 55 return false; 56 return true; 57 } 58 }
再在实体类Student中将主键类包含进来:
Student.java:
1 /** 2 * 对应于student表的实体类,表示学生 3 * 4 * @author hanyuan 5 * @time 2012-8-23 下午09:20:16 6 */ 7 public class Student { 8 private StudentKey studentKey; 9 private int age; 10 private String address; 11 12 public StudentKey getStudentKey() { 13 return studentKey; 14 } 15 16 public void setStudentKey(StudentKey studentKey) { 17 this.studentKey = studentKey; 18 } 19 20 public int getAge() { 21 return age; 22 } 23 24 public void setAge(int age) { 25 this.age = age; 26 } 27 28 public String getAddress() { 29 return address; 30 } 31 32 public void setAddress(String address) { 33 this.address = address; 34 } 35 36 }
实体类Student配置文件:
Student.hbm.xml:
1 <hibernate-mapping> 2 <class name="com.sunflower.entity.Student" table="student"> 3 <!-- 复合主键 --> 4 <composite-id name="studentKey" class="com.sunflower.entity.StudentKey"> 5 <key-property name="studentId" type="long"></key-property> 6 <key-property name="name" type="string"></key-property> 7 </composite-id> 8 9 <property name="age" type="integer"></property> 10 <property name="address" type="string"></property> 11 </class> 12 </hibernate-mapping>
第4行至第7行是复合主键的配置,如果没有将主键属性分离出来单独成一个主键类,那么就不用加 class="com.sunflower.entity.StudentKey".
HibernateUtil.java:
1 /** 2 * 解析配置文件,创建session的工具类 3 * 4 * @author hanyuan 5 * @time 2012-8-23 下午09:42:35 6 */ 7 public class HibernateUtil { 8 private static SessionFactory factory; 9 10 static { 11 Configuration cfg = null; 12 // 解析配置文件 13 try { 14 cfg = new Configuration().configure(); 15 } 16 catch (Exception e) { 17 e.printStackTrace(); 18 } 19 factory = cfg.buildSessionFactory(); 20 } 21 22 /** 23 * 打开一个session 24 */ 25 public static Session getSession() { 26 Session session = factory.openSession(); 27 return session; 28 } 29 30 /** 31 * 关闭session 32 */ 33 public static void closeSession(Session session) { 34 if (null != session) 35 session.close(); 36 } 37 }
第26行中,刚开始写法:Session session = factory.getCurrentSession(), 结果程序报错:session is already closed.
进行测试:
Test.java:
1 public class Test { 2 // // 保存测试 3 // public void save() { 4 // Session session = HibernateUtil.getSession(); 5 // Transaction transaction = session.beginTransaction(); 6 // 7 // try { 8 // StudentKey studentKey = new StudentKey(); 9 // studentKey.setStudentId(20090124); 10 // studentKey.setName("任德华"); 11 // 12 // Student student = new Student(); 13 // student.setStudentKey(studentKey); 14 // student.setAge(22); 15 // student.setAddress("人民路22号"); 16 // session.save(student); 17 // transaction.commit(); 18 // } 19 // catch (Exception e) { 20 // if (null != transaction) 21 // transaction.rollback(); 22 // e.printStackTrace(); 23 // } 24 // finally { 25 // HibernateUtil.closeSession(session); 26 // } 27 // } 28 29 // 查询测试 30 public void get() { 31 Session session = HibernateUtil.getSession(); 32 Transaction transaction = session.beginTransaction(); 33 34 try { 35 StudentKey studentKey = new StudentKey(); 36 studentKey.setStudentId(20090121); 37 studentKey.setName("令狐聪"); 38 39 Student student = (Student) session.get(Student.class, studentKey); 40 transaction.commit(); 41 42 System.out.println("name is:" + student.getStudentKey().getName() + "\n" + "address is:" + student.getAddress()); 43 } 44 catch (Exception e) { 45 if (null != transaction) 46 transaction.rollback(); 47 e.printStackTrace(); 48 } 49 finally { 50 HibernateUtil.closeSession(session); 51 } 52 } 53 54 public static void main(String[] args) { 55 Test test = new Test(); 56 // test.save(); 57 test.get(); 58 } 59 }