zoukankan      html  css  js  c++  java
  • 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 

  • 相关阅读:
    Flask上下文管理及源码刨析
    Python数据库连接池DBUtils
    装饰器的修复wraps,偏函数partial 以及chain
    unity官方案例精讲(第三章)--星际航行游戏Space Shooter
    c#多态性
    C# 继承
    c#类(class)
    一、事件函数的执行顺序(脚本的生命周期)
    一、Vuforia_AR
    四、其它(一)
  • 原文地址:https://www.cnblogs.com/boywwj/p/8031106.html
Copyright © 2011-2022 走看看