Spring Data Jpa 複合主鍵
阿新 • • 發佈:2018-12-21
這次大創有個需求,在資料庫建表時發現,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)
@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());
}
}
}