一、JPA和复合主键的简介

       JPA全称Java Persistence API,是一组用于将数据存入数据库的类和方法的集合。JPA通过JDK5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。JPA的目标是为了整合第三方ORM框架,建立一套标准的API。目前JPA的提供商包括ORacle,Redhat,Eclipse等,提供的产品包括Hiberate, Eclipselink, Toplink, Spring Data JPA等。
        复合主键也就是说需要多个字段才能确定数据库记录中的唯一一行。这样就需要多个字段一起,组成主键,也叫联合主键。比如将PC中所有应用的网络信息保存到一个数据表中,可以将IP和端口设置为复合主键。

       

二、SpringData JPA复合主键 的使用

1、复合主键 和 联合主键

复合主键 : 一张表中 , 两个字段 确定一条唯一数据 ;

联合主键 : 表A , 表 B 两张表 , 通过中间表 , 确定两张表的对应关系 ;
(中间表三个字段 : id , 表A_id, 表B_id) ; 此时中间表的id 称为 联合主键 ;

CREATE TABLE adm_info(sys_id            varchar(20),shop_name         varchar(20),donate_money      decimal(15,2),PRIMARY KEY (sys_id,shop_name)
)

2、spring jpa 复合主键 的使用

方式一   采用 @IdClass 来注解复合主键   配置联合主键

由于表中是两个主键的存在,接下来改造一下我们的实体类:

@Entity
@Data
@IdClass(IcAdmInfoPk.class)
@Table(name = "sys_info")public class IcFilmInfo implements Serializable {private static final long serialVersionUID = 9121531612760132363L;@Id@Column(name = "SysId")private String sId;/*** 商品名*/@Id@Column(name = "ShopName")private String shopName;
}

在两个主键映射的字段上都标注@Id注解
同时新建一个 IcAdmInfoPk 类:

@Data
public class IcAdmInfoPk implements Serializable {private static final long serialVersionUID = -1570834456846591727L;private String sysId;private String shopName;
} 

在实体类上加上@IdClass(IcAdmInfoPk .class)注解

@Query(value = "select * from t_info where SysId = ?1",nativeQuery = true) List<IcAdmInfo> findBySysIdSQL(String sysId);

方式二   自定义接收类  (推荐)

新建一个IcAdmInfoVO类:

@AllArgsConstructor
@Data
public class IcAdmInfoVO {private String sysId;/*** 商品名*/private String shopName;
}
  • 注意要添加 全参构造方法注解@AllArgsConstructor
JAP代码@Query(value = "select new sys.vo.IcAdmInfoVO(t.sysId,t.shopName) from IcAdmInfo t where t.sysId = ?1")
List<IcAdmInfoVO> findBySysId(String sysId);
  • 注意,这个时候这里的@Query注解里面是没有加 nativeQuery = true

方式三  通过复合主键对象+@Embeddable,和实体对象+@Embedded注解

//主键类
@Embeddable
@Data
public class PrimaryKey implements Serializable{private String sysId;/*** 商品名*/private String shopName;
}//实体类
@Entity
@Table(name="A")
public class A{@EmbeddedIdprivate PrimaryKey idCLass;public PrimaryKey getIdCLass() {return idCLass;}public void setIdCLass(PrimaryKey idCLass) {this.idCLass = idCLass;}private String shopName;public String getShopName() {return shopName;}public void setShopName(String ShopName) {this.shopName= shopName;}
}

注意:  

  1) 实现Serializable接口(否则会报错,错误会直接显示); 

  2)在复合主键的类上,使用注解@Embeddable

  3) 有默认的public无参数的构造方法(在我这个实例中,我没有添加有参构造方法,所以采用默认的构造方法)

  如果你在实体类里有有参构造方法,那么一定要有一个无参构造方法,否则运行的时候会报错

org.hibernate.InstantiationException: No default constructor for entity:  : com.my.model.People

这个就是没有默认的构造方法造成的,所以要在实体类中加入默认的无参构造方法。

  4) 重写equalshashCode方法。equals方法用于判断两个对象是否相同,EntityManger通过find方法来查找Entity时,是根据equals的返回值来判断的。hashCode方法返回当前对象的哈希码(我验证EntityManger,不重写也没事。);

三、复合主键的增删改查

3.1 增加操作
带有复合主键的数据库的保存操作,和只有单个主键的保存操作相同,如下:

保存一个实体,repository.save(T entity)
保存多个实体,repository.save(Iterable< T> entities)
保存并立即刷新一个实体,repository.saveAndFlush(T entity)

3.2 查询操作
带有复合主键的数据库的查询操作,可以用复合主键作为整体进行查询

PrimaryKey primaryKey = new PrimaryKey();
primaryKey.setA_id(1);
primaryKey.setB_id(2);
repository.findOne(primaryKey);

3.3 更新操作
更新操作的参考代码如下:

    @Transactional
    @Modifying
    public void update(A a) {
            A finda = repository.findOne(a.getIdCLass());   //这里的repository是继承于JpaRepository的接口
            finda.set(secondlevelEntity.getName());
    }

3.4 删除操作
删除操作的参考代码如下:

 @Transactional
    @Modifying
    public void update(A a) {
            A finda = repository.findOne(a.getIdCLass());   //这里的repository是继承于JpaRepository的接口
            repository.delete(finda);
    }

总结:

针对上面两种方法,貌似都可以解决我们的问题,但是推荐第一种,因为第一种是最贴合数据库的,使用了联合主键的注解,数据库中也是多主键,但是第二种方式可以很好的解决我们在使用JPA去查询的时候接口其他非数据库字段的信息,例如统计等方面。

参考文献

JPA 复合操作

JPA遇到多主键查询

http://blog.csdn.net/qq_35056292/article/details/77892012

SpringData JPA复合主键相关推荐

  1. springboot jpa 复合主键 联合主键

    为什么80%的码农都做不了架构师?>>>    在开发中,数据库中定义了一个复合主键,这时候在映射不稍微处理下会有一点问题.什么does not define an IdClass错 ...

  2. JPA复合主键的使用

    背景 人员信息和组信息的关联表中使用的USER_ID_和GROUP_ID_的联合主键,在维护组人员信息的时候,发现JPA打印的SQL只根据USER_ID_作为条件来更新数据,当B组存在zhangsan ...

  3. java 复合主键,Spring Data Jpa 复合主键的实现

    前言 这次大创有个需求,在数据库建表时发现,user表与project表的关系表 user_project的主键为复合主键: CREATE TABLE user_project( user_id IN ...

  4. JPA之使用复合主键

    文章目录 1. 目标 2. 数据库设计 3. Entity 定义 4. 使用 5. 源码 1. 目标 在设计数据库表的时候,有时候不想定义没有意义的Id作为主键,就可以使用复合主键.这个时候使用JPA ...

  5. Oracle-No.04 Oracle视图加主键解决hibernate复合主键问题

    2019独角兽企业重金招聘Python工程师标准>>> Oracle视图默认是没有主键的,因此在用hibernate反向生成java类时,会自动采用复合主键,多生成一个类名+ID的类 ...

  6. 超键、候选键、主键、外键、联合主键、复合主键

    首先看看各种键的定义: 超键(super key):在关系中能唯一标识元组的属性集称为关系模式的超键(只要有一个键唯一,再随便组其他的键,合起来叫主键) 候选键(candidatekey):不含有多余 ...

  7. hibernate中表的复合主键映射表

    成绩表Cj:学号和课程号是复合主键 映射文件Cj.hbm.xml: <?xml version="1.0"?> <!DOCTYPE hibernate-mappi ...

  8. mysql隐式锁定辅助索引_当Mysql - InnoDB行锁遇到复合主键和多列索引-Go语言中文社区...

    背景 今天在配合其他项目组做系统压测,过程中出现了偶发的死锁问题.分析代码后发现有复合主键的update情况,更新复合主键表时只使用了一个字段更新,同时在事务内又有对该表的insert操作,结果出现了 ...

  9. 复合主键@IdClass

    有时一个实体的主键可能同时为多个,例如同样是之前使用的"CustomerEO"实体,需要通过name和email来查找指定实体,当且仅当name和email的值完全相同时,才认为是 ...

最新文章

  1. update操作报错
  2. HDU2093 考试排名
  3. python使用get函数在字典中加入键_Python使用字典键作为函数名
  4. linux 脚本 expected,Linux | shell与expect结合使用
  5. 孙宇晨凌晨发致歉信:为过度营销、热衷炒作的行为深感愧疚
  6. Python字典的操作与使用
  7. wordpress 伪静态nginx设置
  8. Android快速开发框架Android-query
  9. No.3小白的HTML+CSS心得篇
  10. 微信朋友圈的测试用例
  11. php100视频教程html,PHP100视频教程48:Ajax+PHP快速上手及应用
  12. 手机app测试方法(二)App测试-常见测试点
  13. 体验一命通关 - Java技能树测评
  14. 全球及中国EOG放大器行业运营前景与发展动态研究报告2022版
  15. c++读取图片_四、faster-rcnn源码阅读:数据流读取
  16. 第一章:电商及商品系统概述
  17. obj[key]和0bj.['key']
  18. 飞猪登录器推荐《怪物猎人世界》萌新入坑武器装备推荐
  19. 概率论和数理统计期末复习(仅供个人复习使用)
  20. (C语言)求幂级数展开的部分和

热门文章

  1. 【Flutter 问题系列第 34 篇】Normal、Regular、Medium、Bold 对应的 font-weight 值
  2. 【总结】1227- 干货!学会这几条经验对前端入门事半功倍
  3. 荣耀v40发布会直播地址荣耀v40发布会在线观看入口
  4. 如何使用安卓无障碍服务之uiautomatorviewer.bat(UI Automator Viewer)层级查看器
  5. 湖上建仓全解析:如何打造湖仓一体数据平台 | DEEPNOVA技术荟系列公开课第四期
  6. 201521450014 网络对抗技术实验三 葛文宣
  7. Debian 8.1 安装Broadcom BCM4312无线网卡驱动
  8. Oracle知识点笔记
  9. Mapabc地图----展示地图上的所有点
  10. Elasticsearch分页查询FromSize vs scroll vs search_after