[转自] 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. 8.INSERT INTO 语句 UPDATE 语句

    1. INSERT INTO 语句 INSERT INTO 语句用于向表格中插入新的行. 语法 INSERT INTO 表名称 VALUES (值1, 值2,....) INSERT INTO Per ...

  2. 487C Prefix Product Sequence

    传送门 题目大意 分析 因为n为质数所以i-1的逆元唯一 因此ai唯一 代码 #include<iostream> #include<cstdio> #include<c ...

  3. Django Rest Framework框架 ---- url控制器

    Django Rest Framework框架 ---- url控制器

  4. 【2008nmj】Logistic回归二元分类感知器算法.docx

    给你一堆样本数据(xi,yi),并标上标签[0,1],让你建立模型(分类感知器二元),对于新给的测试数据进行分类. 要将两种数据分开,这是一个分类问题,建立数学模型,(x,y,z),z指示[0,1], ...

  5. 设计模式06: Adapter 适配器模式(结构型模式)

    Adapter 适配器模式(结构型模式) 适配(转换)的概念无处不在:电源转接头.电源适配器.水管转接头... 动机(Motivation)在软件系统中,由于应用环境的变化,常常需要将“一些现存的对象 ...

  6. <%@ include > 与< jsp:include >

    include指令表示在JSP编译时插入一个包含文本或者代码的文件,把文件中的文本静态地包含过去.也就是说,会把被包含的页面拷贝到包含的页面中指令所在的位置. 语法格式:<%@ include ...

  7. Redis 占用Windows系统盘空间23G

    Redis常出现问题总结: 1.当出现修改--maxheap and --heapdir 在启动这两个版本时都会创建一个 RedisQFork.dat文件,我不确定 RedisQFork 文件是否变小 ...

  8. C# worksheet设置Excel样式

    1.例子导出Excel的样式 样式代码 public void Exportdatagridviewtoexcel(string Textname) { SaveFileDialog savedial ...

  9. 去掉html标签方法

    public static string CleanHtml(string strHtml) { strHtml = Regex.Replace(strHtml, @"(\<scrip ...

  10. intellij idea 15,webstorm 最新注册破解

    http://idea.lanyus.com 在激活地址填写上上面的地址就行了,非常简单有效. 亲测idea,webstorm...都可以激活