Spring Data Jpa 复合主键的实现
前言
这次大创有个需求,在数据库建表时发现,user表与project表的关系表user_project的主键为复合主键:
CREATETABLEuser_project( user_idINT(20), project_idINT(20), timestampVARCHAR(50), donate_moneyDOUBLE(10,2), PRIMARYKEY(user_id,project_id) );
在网上看了几篇博客,以及在springboot干货群咨询(感谢夜升额耐心解答)过后总算是做出来了。这里做个总结,方便日后查阅。
正文
这里采用@IdClass注解的方式来实现复合主键;
思路
- 编写一个复合主键类UserProjectMultiKeysClass;
- 通过@IdClass注释在实体中标注复合主键;
- 可以通过EntityManager获取数据,或者是直接在Repository里写方法;
实现
复合主键类
packagecom.hzy.Model;
importjava.io.Serializable;
/**
*Createdbyhuangzhenyangon2017/9/7.
*UserProject的复合主键类
*
*@ParamuserId
*@ParamprojectId
*@Paramtimestamp
*由这三个共同组成复合主键
*/
publicclassUserProjectMultiKeysClassimplementsSerializable{
privateIntegeruserId;
privateIntegerprojectId;
privateStringtimestamp;
//Constructor
publicUserProjectMultiKeysClass(){
}
publicUserProjectMultiKeysClass(IntegeruserId,IntegerprojectId,Stringtimestamp){
this.userId=userId;
this.projectId=projectId;
this.timestamp=timestamp;
}
//SetterandGetter
publicIntegergetUserId(){
returnuserId;
}
publicvoidsetUserId(IntegeruserId){
this.userId=userId;
}
publicIntegergetProjectId(){
returnprojectId;
}
publicvoidsetProjectId(IntegerprojectId){
this.projectId=projectId;
}
publicStringgetTimestamp(){
returntimestamp;
}
publicvoidsetTimestamp(Stringtimestamp){
this.timestamp=timestamp;
}
//***重写hashCode与equals方法***划重点!
@Override
publicinthashCode(){
finalintPRIME=31;
intresult=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());
returnresult;
}
@Override
publicbooleanequals(Objectobj){
if(this==obj){
returntrue;
}
if(obj==null){
returnfalse;
}
if(getClass()!=obj.getClass()){
returnfalse;
}
finalUserProjectMultiKeysClassother=(UserProjectMultiKeysClass)obj;
if(userId==null){
if(other.userId!=null){
returnfalse;
}
}elseif(!userId.equals(other.userId)){
returnfalse;
}
if(projectId==null){
if(other.projectId!=null){
returnfalse;
}
}elseif(!projectId.equals(other.projectId)){
returnfalse;
}
if(timestamp==null){
if(other.timestamp!=null){
returnfalse;
}
}elseif(!timestamp.equals(other.timestamp)){
returnfalse;
}
returntrue;
}
}
注意:
复合主键类必须满足:
1.实现Serializable接口;
2.有默认的public无参数的构造方法;
3.重写equals和hashCode方法。equals方法用于判断两个对象是否相同,EntityManger通过find方法来查找Entity时,是根据equals的返回值来判断的。hashCode方法返回当前对象的哈希码;
实体类
packagecom.hzy.Model;
importjavax.persistence.Entity;
importjavax.persistence.Id;
importjavax.persistence.IdClass;
importjavax.persistence.Table;
importjava.io.Serializable;
/**
*Createdbyhuangzhenyangon2017/9/7.
*
*/
@Entity
@Table(name="user_project")
@IdClass(UserProjectMultiKeysClass.class)
publicclassUserProjectimplementsSerializable{
privatedoubledonateMoney;
privateIntegeruserId;
privateIntegerprojectId;
privateStringtimestamp;
@Id
publicIntegergetUserId(){
returnthis.userId;
}
@Id
publicIntegergetProjectId(){
returnthis.projectId;
}
@Id
publicStringgetTimestamp(){
returnthis.timestamp;
}
//getterandsetter
publicdoublegetDonateMoney(){
returndonateMoney;
}
publicvoidsetDonateMoney(doubledonateMoney){
this.donateMoney=donateMoney;
}
publicvoidsetUserId(IntegeruserId){
this.userId=userId;
}
publicvoidsetProjectId(IntegerprojectId){
this.projectId=projectId;
}
publicvoidsetTimestamp(Stringtimestamp){
this.timestamp=timestamp;
}
@Override
publicStringtoString(){
return"UserProject{"+
"donateMoney="+donateMoney+
",userId="+userId+
",projectId="+projectId+
",timestamp='"+timestamp+'\''+
'}';
}
}
注意:
1.@IdClass标注用于标注实体所使用主键规则的类;
2.在实体中同时标注主键的属性,比如这段代码中的userId,projectId以及timestamp;
获取数据
方法一:通过EntityManager获取,比如方法testUserProjectRepository()
方法二:通过Repository获取;这里记得在extendsJpaRepository
publicinterfaceUserProjectRepositoryextendsJpaRepository{ //根据用户Id,找出用户参与的所有UserProject //TESTPASS List findByUserId(IntegeruserId); //根据项目id,找出参与项目的所有UserProject //TESTPASS List findByProjectId(IntegerprojectId); //根据用户id和项目id找出所有的UserProject //TESTPASS List findByUserIdAndProjectId(IntegeruserId,IntegerprojectId); }
单元测试的代码
packagecom.hzy;
importcom.hzy.Model.UserProject;
importcom.hzy.Model.UserProjectMultiKeysClass;
importcom.hzy.Repository.UserProjectRepository;
importcom.hzy.Service.UserProjectService;
importcom.hzy.Service.UserService;
importorg.junit.Test;
importorg.junit.runner.RunWith;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.boot.test.context.SpringBootTest;
importorg.springframework.test.context.junit4.SpringRunner;
importjavax.persistence.EntityManager;
importjavax.persistence.PersistenceContext;
importjavax.transaction.Transactional;
importjava.util.List;
/**
*Createdbyhuangzhenyangon2017/9/8.
*/
@RunWith(SpringRunner.class)
@SpringBootTest
publicclassUserProejctRepositoryTest{
@Autowired
@PersistenceContext
privateEntityManagerentityManager;
@Autowired
privateUserProjectRepositoryuserProjectRepository;
@Test
publicvoidtestUserProjectRepository(){
UserProjectMultiKeysClassuserProjectMultiKeysClass=
newUserProjectMultiKeysClass(1,1,"2017-09-08");
UserProjectuserProject=entityManager.find(UserProject.class,userProjectMultiKeysClass);
System.out.println(userProject.toString());
}
@Test
publicvoidtestFindByUserId(){
ListuserProjects=userProjectRepository.findByUserId(1);
for(UserProjectuserProject:userProjects){
System.out.println(userProject.toString());
}
}
@Test
publicvoidtestFindByProjectId(){
ListuserProjects=userProjectRepository.findByProjectId(1);
for(UserProjectuserProject:userProjects){
System.out.println(userProject.toString());
}
}
@Test
publicvoidtestFindByUserIdAndProjectId(){
ListuserProjects=userProjectRepository.findByUserIdAndProjectId(1,1);
for(UserProjectuserProject:userProjects){
System.out.println(userProject.toString());
}
}
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。