[转自] 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. Solidity 没名字的function(){...}作用

    官方解释: 这个叫做fallback function,当有人 1. 只发送以太币给合约而不带任何输入数据:2. 调用smart contract时调起了一个不存在的方法.会触发执行这个方法. Wha ...

  2. spark源码阅读之network(3)

    TransportContext用来创建TransportServer和TransportclientFactory,同时使用TransportChannelHandler用来配置channel的pi ...

  3. App测试从入门到精通之性能测试

    好了,上节我们介绍了关于APP测试的功能测试方面一些细节.这一篇我们来介绍一下,关于APP测试过程中的性能测试参考要点,我们需要思考的如下: 响应时间 1.APP安装卸载的响应时间 2.APP各种功能 ...

  4. HTTP文件上传插件开发文档-ASP

    版权所有 2009-2016 荆门泽优软件有限公司 保留所有权利 官方网站:http://www.ncmem.com/ 产品首页:http://www.ncmem.com/webplug/http-u ...

  5. Android Activity的切换动画(overridePendingTransition)

    overridePendingTransition 1.平时Activity的切换是就是从中间弹出来,然后遮盖住之前的Activity.这种效果看到很多后就想给他换成其他的效果,如: 要显示的Acit ...

  6. C# 筛选Datatable、foreach填充DGV,datatable与datarows转换

    public void SelectFG1(string Nane) { string SetText = "卫材代码 like '%" + Nane + "%' or ...

  7. sqlServer2008技术内幕笔记总结(实用的sql方法总结)

    over函数的使用: 1.可以实现基于什么求和,省去group by: select xingming,xingbie,COUNT(*) over() as '总人数' from jbxx_xuesh ...

  8. angular 父组件调用子组件

    import { Component, OnInit, ViewChild } from '@angular/core'; @Component({ selector: 'app-child', te ...

  9. orleans 2.0 教程之-----官方文档翻译,给大家学习ol一个参考

    本人也是英文盲,翻译不对的地方请谅解.由于翻译内容较多,会慢慢更新 orleans简称ol,一些专用词不做翻译.先决条件,读这表文章之前需要了解:actor,es,cqrs 参考链接: https:/ ...

  10. IT学习资源

    介绍个人微信公众平台:Web开发笔记 含有免费学习资源,个人学习笔记,技术文章分享  资源篇 1.webapp书城开发 链接: https://pan.baidu.com/s/1pMHGKrh 密码: ...