[转自] http://blog.csdn.net/happylee6688/article/details/17636801

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

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

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

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

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

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

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

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

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

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

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

public class IPMapKey implements Serializable {

	/**
* @Fields serialVersionUID :3176972128965536016L
*/
private static final long serialVersionUID = 3176972128965536016L; // 主键属性
private String ip; // 主键属性
private String examPlaceId; // 主键属性
private String examId; /**
* 无参数的public构造方法,必须要有
*/
public IPMapKey() { } /**
* 重写了一个带参数的构造方法
* @param ip
* @param examPlaceId
* @param examId
*/
public IPMapKey(String ip, String examPlaceId, String examId) {
this.ip = ip;
this.examId = examId;
this.examPlaceId = examPlaceId;
} public String getIp() {
return ip;
} public void setIp(String ip) {
this.ip = ip;
} public String getExamPlaceId() {
return examPlaceId;
} public void setExamPlaceId(String examPlaceId) {
this.examPlaceId = examPlaceId;
} public String getExamId() {
return examId;
} public void setExamId(String examId) {
this.examId = examId;
} public static long getSerialversionuid() {
return serialVersionUID;
} /**
* 覆盖hashCode方法,必须要有
*/
@Override
public int hashCode() {
final int PRIME = 31;
int result = 1;
result = PRIME * result + (ip == null ? 0 : ip.hashCode());
result = PRIME * result + (examId == null ? 0 : examId.hashCode());
result = PRIME * result + (examPlaceId ==null ? 0 : examPlaceId.hashCode());
return result;
} /**
* 覆盖equals方法,必须要有
*/
@Override
public boolean equals(Object obj) {
if(this == obj) return true;
if(obj == null) return false;
if(!(obj instanceof PaperKey)) return false;
IPMapKey objKey = (IPMapKey)obj;
if(ip.equalsIgnoreCase(objKey.ip) &&
examId.equalsIgnoreCase(objKey.examId) &&
examPlaceId.equalsIgnoreCase(objKey.examPlaceId)) {
return true;
}
return false;
}
}

实体类IPMap(为了方便演示,这里都采用了String类型)

@Entity
@Table(name="TE_IPMap")
@IdClass(IPMapKey.class)
public class IPMap { // 主键,这里需要添加@Id标记
@Id
@Column(name="IP")
private String ip; @Column(name="StudentNo")
private String studentNo; // 主键,这里需要添加@Id标记
@Id
@Column(name="ExamPlaceId")
private String examPlaceId; // 主键,这里需要添加@Id标记
@Id
@Column(name="ExamId", unique=true)
private String examId; @Column(name="AddUser")
private String addUser; @Column(name="TimeStamp")
private String timeStamp; @Column(name="Remark")
private String remark; public String getIp() {
return ip;
} public void setIp(String ip) {
this.ip = ip;
} public String getStudentNo() {
return studentNo;
} public void setStudentNo(String studentNo) {
this.studentNo = studentNo;
} public String getExamPlaceId() {
return examPlaceId;
} public void setExamPlaceId(String examPlaceId) {
this.examPlaceId = examPlaceId;
} public String getExamId() {
return examId;
} public void setExamId(String examId) {
this.examId = examId;
} public String getAddUser() {
return addUser;
} public void setAddUser(String addUser) {
this.addUser = addUser;
} public String getTimeStamp() {
return timeStamp;
} public void setTimeStamp(String timeStamp) {
this.timeStamp = timeStamp;
} public String getRemark() {
return remark;
} public void setRemark(String remark) {
this.remark = remark;
}
}

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

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

——摘自《Effective Java》

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

Hibernate复合主键的注解的更多相关文章

  1. hibernate复合主键

    需要用到实体类Role的主键和Menu的主键结合起来作为实体类RoleMenu的主键,那么通过Hibernate具体实现如下: RoleMenu实体类:(注意该实体类需要实现Serializable接 ...

  2. Hibernate复合主键映射

    目录: 1. 实现方式一:将复合主键对应的属性与实体其他普通属性放在一起 2. 实现方式二:将主键属性提取到一个主键类中,实体类只需包含主键类的一个引用 在日常开发中会遇到这样一种情况,数据库中的某张 ...

  3. 【hibernate/JPA】注解方式实现 复合主键【spring boot】

    1>hibernate/JPA实现复合主键的思路:是将所有的主键属性封装在一个主键类中,提供给需要复合主键的实体类使用. 2>主键类的几点要求: . 使用复合主键的实体类必须实现Seria ...

  4. 【hibernate/JPA】对实体类的的多个字段建立唯一索引,达到复合主键的效果【spring boot】注解创建唯一索引和普通索引

    对实体类的的多个字段建立唯一索引,达到复合主键的效果 package com.sxd.swapping.domain; import lombok.Getter; import lombok.Sett ...

  5. Hibernate 表映射 主键生成策略与复合主键

    主要分析三点: 一.数据表和Java类的映射 : 二.单一主键映射和主键的生成策略 : 三.复合主键的表映射 : 一.数据表和Java类的映射  Hibernate封装了数据库DDL语句,只需要将数据 ...

  6. Hibernate征途(七)之复合主键映射和集合映射

    把这两种映射放到一起说,是因为这两种映射不像前面的复用型映射.数量和方向型映射那么分类鲜明,所以放到了这个“其他”里面. 复合主键映射 在关系模型中,复合主键和其他的主键方式没有很大区别,但是反映到对 ...

  7. 步步为营Hibernate全攻略(四)剪不断理还乱之:复合主键 && 组合映射

    一:复合主键 复合主键即两个或多个字段联合起来作为主键,它的通常做法是将主键相关字段抽取出来放到一个单独的类中,但是这样的类是有要求的: 1.      必须实现序列化接口 2.      必须覆盖e ...

  8. 【Hibernate步步为营】--复合主键映射具体解释

    上篇文章讨论了继承映射,它是对象模型中最主要的特性,对于继承映射它的主要区分是字段类型的不同,所以在生成表结构时须要有新列来标识数据的类型,能够使用<subclass>标签并在标签中加入d ...

  9. Hibernate第三篇【主配置文件、映射文件、复合主键映射】

    前言 目前已经学了如何搭建Hibernate的开发环境,以及Hibernate对应的API了-在快速入门还没讲解的就是配置文件是怎么配置的.因此,本博文主要讲解主配置文件以及映射配置文件.. 主配置文 ...

随机推荐

  1. SpringMVC——拦截器

    Spring MVC也可以使用拦截器对请求进行拦截处理,用户可以自定义拦截器来实现特定的功能,自定义的拦截器必须实现HandlerInterceptor接口 preHandle():这个方法在业务处理 ...

  2. hdu 4768 Flyer (异或操作的应用)

    2013年长春网络赛1010题 继巴斯博弈(30分钟)签到后,有一道必过题(一眼即有思路). 思路老早就有(40分钟):倒是直到3小时后才被A掉.期间各种换代码姿态! 共享思路: unlucky st ...

  3. HandleErrorAttribute只能处理httpStatusCode为500的异常(服务器异常)

    HandleErrorAttribute源代码: [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited ...

  4. jquery操作select(取值,设置选中) 基础

    每一次操作select的时候,总是要出来翻一下资料,不如自己总结一下,以后就翻这里了. 比如<select class="selector"></select&g ...

  5. Oracle下载及安装

    Oracle   下载及安装 一.官方下地址:   http://www.oracle.com/technetwork/database/enterprise-edition/downloads/in ...

  6. 【leetcode 5040. 边框着色】解题报告

    方法一:dfs的非递归形式 using ll=long long; const ll MAXN=50LL; unordered_set<ll> vis,mark; vector<ve ...

  7. NSRect 位置和尺寸

    前言 结构体 这个结构体用来表示事物的坐标点和宽高度. typedef CGRect NSRect; struct CGRect { CGPoint origin; CGSize size; }; t ...

  8. ASP.NET -- 获取浏览器信息

    1. 获取浏览器信息 private void GetBrowserInfo() { StringBuilder sb = new StringBuilder(); sb.AppendLine(str ...

  9. [原创]ObjectARX开发环境搭建之VS2010+ObjectARX2012Wizard+Addin工具条问题修复

    目前ObjectARX版本越来越高,也越来越简化开发,如果需要同时开发低版本和高版本的ARX程序,就需要搭建批量编译环境,以满足ARX开发的需要. 批量编译的搭建网络上已经有了很多的教程,基本上都是基 ...

  10. HTML5+CSS实现三列布局自适应

    利用CSS的float属性可以将元素并排,做出三列并排的布局. 如这样的效果 实现的原理:只要将3个元素设置float属性,属性值为left,同时指定不同比例的宽度,及高度. 下面是实现代码 < ...