Implementation of Spring Data Jpa Compound Primary Key

  • 2021-07-18 08:04:04
  • OfStack

Preface

There is a requirement in this big creation. When building tables in the database, it is found that the primary key of the relational table user_project between user table and project table is a composite primary key:


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)
);

After reading several blogs on the Internet and consulting the dry goods group of spring boot (thanks for the patient answer of the night increase), it was finally made. Here is a summary for future reference.

Text

Here, @ IdClass annotation is used to realize compound primary key.

Train of thought

Write a composite primary key class UserProjectMultiKeysClass;; Label the compound primary key in the entity through @ IdClass annotation; You can get data through EntityManager, or write methods directly in Repository;

Realization

Compound primary key class


package com.hzy.Model;

import java.io.Serializable;

/**
 * Created by huangzhenyang on 2017/9/7.
 * UserProject Compound primary key class of 
 *
 * @Param userId
 * @Param projectId
 * @Param timestamp
 *  By this 3 Together, they form a composite primary key 
 */
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;
  }

  // *** Rewrite hashCode And equals Method ***  Focus! 
  @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;
  }
}

Note:

The composite primary key class must satisfy:
1. Implement Serializable interface;
2. There is a default construction method of public without parameters;
3. Override the equals and hashCode methods. equals method is used to judge whether two objects are the same. When EntityManger searches for Entity by find method, it is judged according to the return value of equals. The hashCode method returns the hash code of the current object;

Entity class


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 + '\'' +
        '}';
  }
}

Note:
1. @ IdClass annotates the class used to annotate the primary key rules used by entities;
2. Mark the attributes of the primary key in the entity at the same time, such as userId, projectId and timestamp in this code;

Get data

Method 1: Get through EntityManager, such as method testUserProjectRepository ()

Method 2: Obtain through Repository; Remember here in extends JpaRepository < UserProject,UserProjectMultiKeysClass > The primary key class of id is specified as the composite primary key class UserProjectMultiKeysClass when


public interface UserProjectRepository extends JpaRepository<UserProject,UserProjectMultiKeysClass>{
  //  According to the user Id, Find out all the users participated in UserProject
  // TEST PASS
  List<UserProject> findByUserId(Integer userId);

  //  According to the project id, Find out all the participating projects UserProject
  // TEST PASS
  List<UserProject> findByProjectId(Integer projectId);

  //  According to the user id And projects id  Find out all the UserProject
  // TEST PASS
  List<UserProject> findByUserIdAndProjectId(Integer userId,Integer projectId);
}

Code for unit tests


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)
@SpringBootTest
public 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());
    }
  }
}

Related articles: