Spring Data Jpa 复合主键的实现

 更新时间:2019年04月12日 11:37:21   作者:冬天饮雪水  
这篇文章主要介绍了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());
    }
  }
}

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

相关文章

  • Java/Android引用类型及其使用全面分析

    Java/Android引用类型及其使用全面分析

    下面小编就为大家带来一篇Java/Android引用类型及其使用全面分析。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-09-09
  • @RequestBody注解的原理及使用技巧分享

    @RequestBody注解的原理及使用技巧分享

    这篇文章主要介绍了@RequestBody注解的原理及使用技巧分享,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-10-10
  • java读取其他服务接口返回的json数据示例代码

    java读取其他服务接口返回的json数据示例代码

    这篇文章主要给大家介绍了关于java读取其他服务接口返回的json数据的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
    2018-03-03
  • MyBatis-Plus通过插件将数据库表生成Entiry,Mapper.xml,Mapper.class的方式

    MyBatis-Plus通过插件将数据库表生成Entiry,Mapper.xml,Mapper.class的方式

    今天小编就为大家分享一篇关于MyBatis-Plus通过插件将数据库表生成Entiry,Mapper.xml,Mapper.class的方式,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-02-02
  • 浅谈java对象结构 对象头 Markword

    浅谈java对象结构 对象头 Markword

    这篇文章主要介绍了浅谈java对象结构 对象头 Markword,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-10-10
  • Java中各种集合判空方法总结

    Java中各种集合判空方法总结

    最近接触集合比较多,经常对于集合是否为空做判断,下面这篇文章主要给大家介绍了关于Java中各种集合判空方法总结的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2023-12-12
  • 详解JAVA中的Collection接口和其主要实现的类

    详解JAVA中的Collection接口和其主要实现的类

    这篇文章主要介绍了JAVA中的Collection接口和其主要实现的类,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-03-03
  • MyBatis缓存功能原理及实例解析

    MyBatis缓存功能原理及实例解析

    这篇文章主要介绍了MyBatis缓存功能原理及实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-03-03
  • Java设计模式之建造者模式的示例详解

    Java设计模式之建造者模式的示例详解

    建造者模式,是一种对象构建模式 它可以将复杂对象的建造过程抽象出来,使这个抽象过程的不同实现方法可以构造出不同表现的对象。本文将通过示例讲解建造者模式,需要的可以参考一下
    2022-10-10
  • Java调用商品详情API的项目实践

    Java调用商品详情API的项目实践

    在现代电子商务网站中,商品详情API是一个重要的组件,本文就来介绍一下Java调用商品详情API的项目实践,具有一定的参考价值,感兴趣的可以了解一下
    2023-11-11

最新评论