Hibernate复合主键的注解

 最近做项目用到了hibernate框架,采用了纯面向对象的思想,使用ORM映射实体。在开发中,实体中出现了复合主键,不再是单一的属性作主键,由于采用了注解的方式,就不再使用xml文件进行配置了,而是直接在实体中进行注释。


Hibernate注解规范的文档中提供了三种方法

     1. 将组件类注解为@Embeddable,并将组件的属性注解为@Id;

     2. 将组件的属性注解为@Embeddable;

     3. 将类注解为@IdClass,并将该实体中所有主键属性注解为@Id。

这里,我采用的是第三种方法——@IdClass,下面就是具体的代码,大家一块讨论一下。


       首先,需要说明的是,采用@IdClass方式,需要根据所有的主键属性,建立一个主键类,该主键类包含所有的主键,而且,作为主键类,需要满足以下要求:

    1. 主键类必须实现序列化接口(implements Serializable);

    2. 主键类必须有默认的public无参数的构造方法;

    3. 主键类必须覆盖equals和hashCode方法。


主键类IPMapKey(为了方便演示,这里都采用了String类型)

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public class IPMapKey implements Serializable {  
  2.   
  3.     /** 
  4.      * @Fields serialVersionUID :3176972128965536016L 
  5.      */  
  6.     private static final long serialVersionUID = 3176972128965536016L;  
  7.       
  8.     // 主键属性  
  9.     private String ip;  
  10.       
  11.     // 主键属性  
  12.     private String examPlaceId;  
  13.       
  14.     // 主键属性  
  15.     private String examId;  
  16.   
  17.     /** 
  18.      * 无参数的public构造方法,必须要有 
  19.      */  
  20.     public IPMapKey() {  
  21.           
  22.     }  
  23.       
  24.     /** 
  25.      * 重写了一个带参数的构造方法 
  26.      * @param ip 
  27.      * @param examPlaceId 
  28.      * @param examId 
  29.      */  
  30.     public IPMapKey(String ip, String examPlaceId, String examId) {  
  31.         this.ip = ip;  
  32.         this.examId = examId;  
  33.         this.examPlaceId = examPlaceId;  
  34.     }  
  35.       
  36.     public String getIp() {  
  37.         return ip;  
  38.     }  
  39.   
  40.     public void setIp(String ip) {  
  41.         this.ip = ip;  
  42.     }  
  43.   
  44.     public String getExamPlaceId() {  
  45.         return examPlaceId;  
  46.     }  
  47.   
  48.     public void setExamPlaceId(String examPlaceId) {  
  49.         this.examPlaceId = examPlaceId;  
  50.     }  
  51.   
  52.     public String getExamId() {  
  53.         return examId;  
  54.     }  
  55.   
  56.     public void setExamId(String examId) {  
  57.         this.examId = examId;  
  58.     }  
  59.   
  60.     public static long getSerialversionuid() {  
  61.         return serialVersionUID;  
  62.     }  
  63.   
  64.     /** 
  65.      * 覆盖hashCode方法,必须要有 
  66.      */  
  67.     @Override  
  68.     public int hashCode() {  
  69.         final int PRIME = 31;  
  70.         int result = 1;  
  71.         result = PRIME * result + (ip == null ? 0 : ip.hashCode());  
  72.         result = PRIME * result + (examId == null ? 0 : examId.hashCode());  
  73.         result = PRIME * result + (examPlaceId ==null ? 0 : examPlaceId.hashCode());  
  74.         return result;  
  75.     }  
  76.   
  77.     /** 
  78.      * 覆盖equals方法,必须要有 
  79.      */  
  80.     @Override  
  81.     public boolean equals(Object obj) {  
  82.         if(this == obj) return true;  
  83.         if(obj == nullreturn false;  
  84.         if(!(obj instanceof PaperKey)) return false;  
  85.         IPMapKey objKey = (IPMapKey)obj;  
  86.         if(ip.equalsIgnoreCase(objKey.ip) &&  
  87.                 examId.equalsIgnoreCase(objKey.examId) &&   
  88.                 examPlaceId.equalsIgnoreCase(objKey.examPlaceId)) {  
  89.             return true;  
  90.         }  
  91.         return false;  
  92.     }  
  93. }</span>  


实体类IPMap(为了方便演示,这里都采用了String类型)
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <span style="font-family:Microsoft YaHei;font-size:14px;">@Entity  
  2. @Table(name="TE_IPMap")  
  3. @IdClass(IPMapKey.class)  
  4. public class IPMap {  
  5.   
  6.     // 主键,这里需要添加@Id标记  
  7.     @Id  
  8.     @Column(name="IP")  
  9.     private String ip;  
  10.       
  11.     @Column(name="StudentNo")  
  12.     private String studentNo;  
  13.       
  14.     // 主键,这里需要添加@Id标记  
  15.     @Id  
  16.     @Column(name="ExamPlaceId")  
  17.     private String examPlaceId;  
  18.       
  19.     // 主键,这里需要添加@Id标记  
  20.     @Id  
  21.     @Column(name="ExamId", unique=true)  
  22.     private String examId;  
  23.       
  24.     @Column(name="AddUser")  
  25.     private String addUser;  
  26.       
  27.     @Column(name="TimeStamp")  
  28.     private String timeStamp;  
  29.       
  30.     @Column(name="Remark")  
  31.     private String remark;  
  32.   
  33.     public String getIp() {  
  34.         return ip;  
  35.     }  
  36.   
  37.     public void setIp(String ip) {  
  38.         this.ip = ip;  
  39.     }  
  40.   
  41.     public String getStudentNo() {  
  42.         return studentNo;  
  43.     }  
  44.   
  45.     public void setStudentNo(String studentNo) {  
  46.         this.studentNo = studentNo;  
  47.     }  
  48.   
  49.     public String getExamPlaceId() {  
  50.         return examPlaceId;  
  51.     }  
  52.   
  53.     public void setExamPlaceId(String examPlaceId) {  
  54.         this.examPlaceId = examPlaceId;  
  55.     }  
  56.   
  57.     public String getExamId() {  
  58.         return examId;  
  59.     }  
  60.   
  61.     public void setExamId(String examId) {  
  62.         this.examId = examId;  
  63.     }  
  64.   
  65.     public String getAddUser() {  
  66.         return addUser;  
  67.     }  
  68.   
  69.     public void setAddUser(String addUser) {  
  70.         this.addUser = addUser;  
  71.     }  
  72.   
  73.     public String getTimeStamp() {  
  74.         return timeStamp;  
  75.     }  
  76.   
  77.     public void setTimeStamp(String timeStamp) {  
  78.         this.timeStamp = timeStamp;  
  79.     }  
  80.   
  81.     public String getRemark() {  
  82.         return remark;  
  83.     }  
  84.   
  85.     public void setRemark(String remark) {  
  86.         this.remark = remark;  
  87.     }  
  88. }

       在主键类中,为了能使集合框架中的类(如HashMap)正常工作,必须同时覆盖equals和hashCode方法,而且不要由于写错参数类型,而重载了这个方法,却没有覆盖它们。

       覆盖equals时总要覆盖hashCode,一个很常见的错误根源在没有覆盖hashCode方法。在每个覆盖了equals方法的类中,也必须覆盖hashCode方法。如果不这样做的话,就会违反Object.hashCode的通用约定,从而导致该类无法结合所有基于散列的集合一起正常工作,这样的集合包括HashMap、HashSet和Hashtable。

——摘自《Effective Java

       equals方法用于判断传入的对象是否相同,EntityManager通过find方法来查找Entity时,是根据equals方法的返回值来判断的。hashCode方法返回当前对象的哈希码,生成的hashCode相同的概率越小越好。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值