Spring Data Jpa 复合主键的实现

时间:2021-05-20

前言

这次大创有个需求,在数据库建表时发现,user表与project表的关系表 user_project的主键为复合主键:

CREATE TABLE user_project( user_id INT(20), project_id INT(20), timestamp VARCHAR (50), donate_money DOUBLE(10,2), PRIMARY KEY (user_id,project_id));

在网上看了几篇博客,以及在spring boot干货群咨询(感谢夜升额耐心解答)过后总算是做出来了。这里做个总结,方便日后查阅。

正文

这里采用@IdClass注解的方式来实现复合主键;

思路

  • 编写一个复合主键类UserProjectMultiKeysClass;
  • 通过@IdClass注释在实体中标注复合主键;
  • 可以通过EntityManager获取数据,或者是直接在Repository 里写方法;
  • 实现

    复合主键类

    package com.hzy.Model;import java.io.Serializable;/** * Created by huangzhenyang on 2017/9/7. * UserProject的复合主键类 * * @Param userId * @Param projectId * @Param timestamp * 由这三个共同组成复合主键 */public class UserProjectMultiKeysClass implements Serializable { private Integer userId; private Integer projectId; private String timestamp; //Constructor public UserProjectMultiKeysClass() { } public UserProjectMultiKeysClass(Integer userId, Integer projectId, String timestamp) { this.userId = userId; this.projectId = projectId; this.timestamp = timestamp; } //Setter and Getter public Integer getUserId() { return userId; } public void setUserId(Integer userId) { this.userId = userId; } public Integer getProjectId() { return projectId; } public void setProjectId(Integer projectId) { this.projectId = projectId; } public String getTimestamp() { return timestamp; } public void setTimestamp(String timestamp) { this.timestamp = timestamp; } // ***重写hashCode与equals方法*** 划重点! @Override public int hashCode() { final int PRIME = 31; int result = 1; result = PRIME * result + ((userId == null) ? 0 : userId.hashCode()); result = PRIME * result + ((projectId == null) ? 0 : projectId.hashCode()); result = PRIME * result + ((timestamp == null) ? 0 : timestamp.hashCode()); return result; } @Override public boolean equals(Object obj){ if(this == obj){ return true; } if(obj == null){ return false; } if(getClass() != obj.getClass()){ return false; } final UserProjectMultiKeysClass other = (UserProjectMultiKeysClass)obj; if(userId == null){ if(other.userId != null){ return false; } }else if(!userId.equals(other.userId)){ return false; } if(projectId == null){ if(other.projectId != null){ return false; } }else if(!projectId.equals(other.projectId)){ return false; } if(timestamp == null){ if(other.timestamp != null){ return false; } }else if(!timestamp.equals(other.timestamp)){ return false; } return true; }}

    注意:

    复合主键类必须满足:
    1. 实现Serializable接口;
    2. 有默认的public无参数的构造方法;
    3. 重写equals和hashCode方法。equals方法用于判断两个对象是否相同,EntityManger通过find方法来查找Entity时,是根据equals的返回值来判断的。hashCode方法返回当前对象的哈希码;

    实体类

    package com.hzy.Model;import javax.persistence.Entity;import javax.persistence.Id;import javax.persistence.IdClass;import javax.persistence.Table;import java.io.Serializable;/** * Created by huangzhenyang on 2017/9/7. * */@Entity@Table(name = "user_project")@IdClass(UserProjectMultiKeysClass.class)public class UserProject implements Serializable { private double donateMoney; private Integer userId; private Integer projectId; private String timestamp; @Id public Integer getUserId(){ return this.userId; } @Id public Integer getProjectId(){ return this.projectId; } @Id public String getTimestamp(){ return this.timestamp; } //getter and setter public double getDonateMoney() { return donateMoney; } public void setDonateMoney(double donateMoney) { this.donateMoney = donateMoney; } public void setUserId(Integer userId) { this.userId = userId; } public void setProjectId(Integer projectId) { this.projectId = projectId; } public void setTimestamp(String timestamp) { this.timestamp = timestamp; } @Override public String toString() { return "UserProject{" + "donateMoney=" + donateMoney + ", userId=" + userId + ", projectId=" + projectId + ", timestamp='" + timestamp + '\'' + '}'; }}

    注意:
    1. @IdClass标注用于标注实体所使用主键规则的类;
    2. 在实体中同时标注主键的属性,比如这段代码中的userId,projectId以及timestamp ;

    获取数据

    方法一: 通过EntityManager获取,比如方法testUserProjectRepository()

    方法二:通过Repository获取;这里记得在extends JpaRepository<UserProject,UserProjectMultiKeysClass>时把id的主键类指定为复合主键类UserProjectMultiKeysClass

    public interface UserProjectRepository extends JpaRepository<UserProject,UserProjectMultiKeysClass>{ // 根据用户Id,找出用户参与的所有UserProject // TEST PASS List<UserProject> findByUserId(Integer userId); // 根据项目id,找出参与项目的所有UserProject // TEST PASS List<UserProject> findByProjectId(Integer projectId); // 根据用户id和项目id 找出所有的UserProject // TEST PASS List<UserProject> findByUserIdAndProjectId(Integer userId,Integer projectId);}

    单元测试的代码

    package com.hzy;import com.hzy.Model.UserProject;import com.hzy.Model.UserProjectMultiKeysClass;import com.hzy.Repository.UserProjectRepository;import com.hzy.Service.UserProjectService;import com.hzy.Service.UserService;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.test.context.junit4.SpringRunner;import javax.persistence.EntityManager;import javax.persistence.PersistenceContext;import javax.transaction.Transactional;import java.util.List;/** * Created by huangzhenyang on 2017/9/8. */@RunWith(SpringRunner.class)@SpringBootTestpublic class UserProejctRepositoryTest { @Autowired @PersistenceContext private EntityManager entityManager; @Autowired private UserProjectRepository userProjectRepository; @Test public void testUserProjectRepository(){ UserProjectMultiKeysClass userProjectMultiKeysClass = new UserProjectMultiKeysClass(1, 1, "2017-09-08"); UserProject userProject = entityManager.find(UserProject.class,userProjectMultiKeysClass); System.out.println(userProject.toString()); } @Test public void testFindByUserId(){ List<UserProject> userProjects = userProjectRepository.findByUserId(1); for(UserProject userProject:userProjects){ System.out.println(userProject.toString()); } } @Test public void testFindByProjectId(){ List<UserProject> userProjects = userProjectRepository.findByProjectId(1); for(UserProject userProject:userProjects){ System.out.println(userProject.toString()); } } @Test public void testFindByUserIdAndProjectId(){ List<UserProject> userProjects = userProjectRepository.findByUserIdAndProjectId(1,1); for(UserProject userProject:userProjects){ System.out.println(userProject.toString()); } }}

    以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

    声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。

    相关文章