服务器之家

服务器之家 > 正文

Spring Data Jpa 复合主键的实现

时间:2021-07-31 12:26     来源/作者:冬天饮雪水

前言

这次大创有个需求,在数据库建表时发现,user表与project表的关系表 user_project的主键为复合主键

?
1
2
3
4
5
6
7
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 里写方法;

实现

复合主键类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
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方法返回当前对象的哈希码;

实体类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
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);
}

单元测试的代码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
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());
    }
  }
}

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

原文链接:https://blog.csdn.net/qq_35056292/article/details/77892012

标签:

相关文章

热门资讯

2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全 2019-12-26
yue是什么意思 网络流行语yue了是什么梗
yue是什么意思 网络流行语yue了是什么梗 2020-10-11
背刺什么意思 网络词语背刺是什么梗
背刺什么意思 网络词语背刺是什么梗 2020-05-22
苹果12mini价格表官网报价 iPhone12mini全版本价格汇总
苹果12mini价格表官网报价 iPhone12mini全版本价格汇总 2020-11-13
2021德云社封箱演出完整版 2021年德云社封箱演出在线看
2021德云社封箱演出完整版 2021年德云社封箱演出在线看 2021-03-15
返回顶部