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. 重写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());

}

}

}

以上是 Spring Data Jpa 复合主键的实现 的全部内容, 来源链接: utcz.com/z/354624.html

回到顶部