首页 > 编程 > Java > 正文

Spring Data Jpa 复合主键的实现

2019-11-26 09:05:30
字体:
来源:转载
供稿:网友

前言

这次大创有个需求,在数据库建表时发现,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)@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());    }  }}

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

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表