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(){ List userProjects=userProjectRepository.findByProjectId(1); for(UserProjectuserProject:userProjects){ System.out.println(userProject.toString()); } } @Test publicvoidtestFindByUserIdAndProjectId(){ List userProjects=userProjectRepository.findByUserIdAndProjectId(1,1); for(UserProjectuserProject:userProjects){ System.out.println(userProject.toString()); } } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。