1. 程式人生 > >Spring Data Jpa 複合主鍵

Spring Data Jpa 複合主鍵

這次大創有個需求,在資料庫建表時發現,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註解的方式來實現複合主鍵;

思路

  1. 編寫一個複合主鍵類UserProjectMultiKeysClass;
  2. 通過@IdClass註釋在實體中標註複合主鍵;
  3. 可以通過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. 重寫equalshashCode方法。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

獲取資料

  1. 方法一: 通過EntityManager獲取,比如方法testUserProjectRepository()
  2. 方法二:通過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)
@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());
        }
    }
}