SpringData JPA复合主键

  上一篇博客简单介绍了SpringData JPA实现简单的CRUD,分页与多条件的排序,那里的主键类型是Long,有时我们会遇到主键不是一个的,复合主键,经过调研如下。确定一个人,不能只根据他的姓名来确定,因为会有重名,现在我们假设姓名、身份证号确定唯一一个人。

复合主键:一张表存在多个字段共同组成一个主键,这多个字段的组合不能重复,但是单独一个可以重复。

例子:姓名和省份证号共同组成了主键

一、Spring Data Jpa 复合主键

1.1、编写一个复合主键类:PeopleKey 

@Embeddable
public class PeopleKey implements Serializable  {

	@Column(name = "name")
	private String name;

	@Column(name = "idcardno")
	private String idcardno;
	// 省略setter,getter方法

	@Override
	public String toString() {
		return "PeopleKey [name=" + name + ", idcardno=" + idcardno + "]";
	}
} 

  注意:  

  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,不重写也没事。);

1.2、编写实体类:People

package com.my.model;

import javax.persistence.*;
@Entity
@Table(name = "people")
//@IdClass(PeopleKey.class)
public class People extends PeopleKey{
    // 复合主键要用这个注解
	@EmbeddedId
	private PeopleKey id;

	@Column(name = "age")
	private int age;

	@Column(name = "address")
	private String address;

	// 省略setter,getter方法
	@Override
	public String toString() {
		return "People [id=" + id + ", age=" + age + ", address=" + address
				+ "]";
	}
}

1.3 测试:

@Service
public class PeopleService {

	@Resource
	private PeopleRepository peopleRepository;

	public People findOne() {
		PeopleKey peopleKey = new PeopleKey();
		peopleKey.setName("张三");
		peopleKey.setIdcardno("340123");
		People people = peopleRepository.findOne(peopleKey);
		return people;
	}

}

控制台上的输出结果:

People [id=PeopleKey [name=张三, idcardno=340123], age=3, address=分解分] 

二、采用@IdClass来注解复合主键

过程和@Embeddable差不多,这里直接贴例子。

@Entity
@Table(name = "people")
@IdClass(PeopleKey.class)
public class People  implements Serializable {

//	@EmbeddedId
//	private PeopleKey id;

	@Id
	@Column(name = "name")
	private String name;
	@Id
	@Column(name = "idcardno")
	private String idcardno;

	@Column(name = "age")
	private int age;

	@Column(name = "address")
	private String address;

}
public class PeopleKey implements Serializable  {
//	@Id
//	@Column(name = "name")
	private String name;
//	@Id
//	@Column(name = "idcardno")
	private String idcardno;

}

采用这个方法的我参考博客里有一篇,写的比较详细,但是感觉这个方法不好,本身就已经在PeopleKey中把主键给封装了,但是在实体类People中还要把复合主键给加入进去,不够简介,采用第一种方法,就很简单,而且也体现了Java类封装的思想。

三、EntityManager的验证,直接上代码

package com.my.model;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.Entity;
import javax.persistence.Id;
//@Embeddable
public class PeopleKey implements Serializable  {
//	@Id
//	@Column(name = "name")
	private String name;
//	@Id
//	@Column(name = "idcardno")
	private String idcardno;

	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getIdcardno() {
		return idcardno;
	}
	public void setIdcardno(String idcardno) {
		this.idcardno = idcardno;
	}

	@Override
	public String toString() {
		return "PeopleKey [name=" + name + ", idcardno=" + idcardno + "]";
	}	

}

  

package com.my.model;

import java.io.Serializable;

import javax.persistence.*;
@Entity
@Table(name = "people")
@IdClass(PeopleKey.class)
public class People  {

//	@EmbeddedId
//	private PeopleKey id;

	@Column(name = "age")
	private int age;

	@Column(name = "address")
	private String address;

//	public PeopleKey getId() {
//		return id;
//	}
//
//	public void setId(PeopleKey id) {
//		this.id = id;
//	}
//
	@Id
	@Column(name = "name")
	private String name;
	@Id
	@Column(name = "idcardno")
	private String idcardno;

	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getIdcardno() {
		return idcardno;
	}
	public void setIdcardno(String idcardno) {
		this.idcardno = idcardno;
	}
	public int getAge() {
		return age;
	}

	public People() {
		super();
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	@Override
	public String toString() {
		return "People [age=" + age + ", address=" + address + ", name=" + name
				+ ", idcardno=" + idcardno + "]";
	}

}

测试:

	 @RequestMapping(value = "/useEntityManager")
	 public void findUseEntityManager() throws Exception
	    {
		 	PeopleKey peopleKey = new PeopleKey();
			peopleKey.setName("张三");
			peopleKey.setIdcardno("340123");
	         People people = entityManager.find(People.class,peopleKey);
	         System.out.println(people.toString());
	    } 

结果:

People [age=3, address=分解分, name=张三, idcardno=340123]

  

参考博客:

1、https://www.cnblogs.com/linjiqin/archive/2011/03/09/1978680.html

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

时间: 2024-10-03 05:46:41

SpringData JPA复合主键的相关文章

hibernate 复合主键映射

第一次写博客,只想把工作中遇到的问题记下来. 最近做了一个二次开发的改造,改完之后被告知数据表主键根据需求需要用复合主键,因为本人菜鸟一枚,复合主键从未用过,只能靠度娘 网上给出的复合主键映射大致就两种 第一种:将复合主键对应的属性与实体其他普通属性放在一起 /*实体类.复合主键必须实现Serialzable接口*/ public class User implements Serialzable { private static final long serialVersionUID=1L;/

hibernate复合主键

需要用到实体类Role的主键和Menu的主键结合起来作为实体类RoleMenu的主键,那么通过Hibernate具体实现如下: RoleMenu实体类:(注意该实体类需要实现Serializable接口),且在Hibernate.cfg.xml文件中,复合主键用到的类的映射的xml文件需要放在改类映射的xml文件之前. package com.cdms.model; import java.io.Serializable; /** * 角色权限类 * @author MY * */ public

(九)Hibernate 的复合主键

一.什么是复合主键? 一张表的主键是由多个字段组成,这个主键就被称为复合主键.  主键是唯一确定某条记录的字段,比如公民的身份证号就是一个主键,因为由身份证号这个主键就可以确定 某个公民.   有一种情况,比如学生成绩这张表中,一个学号无法唯一确定这个学生的成绩,因为这个学生有多科成绩,这时候"学号+学科"才是主键,两者结合才能唯一确定一条记录,也就是成绩. 二.hibernate生成含有复合主键表的映射bean 2.1 创建有复合主键的表   这张表有复合主键 2.2 生成映射文件

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

主要分析三点: 一.数据表和Java类的映射 : 二.单一主键映射和主键的生成策略 : 三.复合主键的表映射 : 一.数据表和Java类的映射  Hibernate封装了数据库DDL语句,只需要将数据表和类之间实现映射,即可对数据表进行操作. 示例:数据库中存在表interface_admin.ds_area,实现表和类之间映射,其中单一主键oggKeyId,使用主键自动生成策略UUID,具体第二点进行阐述 . package com.pec.model; import java.io.Seri

什么是复合主键

复合主键应该是一张表中,由几个字段来定的唯一性,因为某几列的组合就能唯一确立一条记录,因此他们的组合为一张表的主键.通常,一张表有一个主键字段,是唯一非空的.而复合主键是一张表由几个字段来定唯一性,即每条记录的col1和col2字段唯一. 当一个字段无法确定唯一性的时候,需要其他字段来一起形成唯一性.就是说用来组成唯一性的字段如果有多个就是联合主键如: 学生成绩(学号,课程号,成绩) --那学号和课程号就可以做为联合主键. 因为学号和课程号决定了成绩.也就是说.你要知道成绩..你就要知道学号,知

【Hibernate步步为营】--复合主键映射详解

本题是最基本的分段树操作了.或者一般叫线段树,不过好像和线段没什么关系,只是分段了. 不使用lazy标志,更新只是更新单点. 如果不使用分段树,那么更新时间效率只需要O(1),使用分段树更新效率就需要O(lgn)了. 但是不是用分段树,那么查询的时间效率是O(n),而分段树查询效率是O(lgn) 这就是amortize分摊了时间,而且lgn真的很快,数据不是非常巨大的时候,接近常数了. 故此本题需要使用分段树. #include <cstdio> class EnemyInfo { stati

对逻辑主键、业务主键和复合主键的思考

转载的: http://blog.csdn.net/sunrise918/article/details/5575054 这几天对逻辑主键.业务主键和复合主键进行了一些思考,也在网上搜索了一下相关的讨论,相关讨论可以看最下面的参考链接.下面是自己基于 SQL Server 做的一些总结,其他数据库(Oracle.MySQL.DB2.......)应该也类似吧.这个只是自己一时的思考,如有不当请告知,重新思考后再修 正. ? ? 定义(部分定义来源于 SQL Server 联机丛书): 主键(PR

hinernate复合主键操作方法

目录: 1. 实现方式一:将复合主键对应的属性与实体其他普通属性放在一起 2. 实现方式二:将主键属性提取到一个主键类中,实体类只需包含主键类的一个引用 在日常开发中会遇到这样一种情况,数据库中的某张表需要多个字段列才能唯一确定一行记录,这时表需要使用复合主键.面对这样的情况Hibernate为我们提供了两种方式来解决复合主键问题. 方式一:将复合主键对应的属性与实体其他普通属性放在一起 例如实体类People中"id"和"name"属性对应复合主键: People

Laravel中定义复合主键

laravel默认主键是id,但有的时候我们建表时可能会需要用到复合主键,那么laravel中使用Eloquent Medel如何定义复合主键呢?直接上代码. 首先在app目录先创建文件 Traits/HasCompositePrimaryKey 内容如下: // Adjust this to match your model namespace! namespace App\Traits; use Illuminate\Database\Eloquent\Builder; trait HasC