JPA联合主键使用
在实际工作中,我们会经常遇到联合主键的情况,所以我用简单例子列举JPA两种实现联合主键的方式。
1、如何通过@IdClass 实现联合主键
第一步:新建一个UserInfoID类,里面是联合主键
@Data @Builder @NoArgsConstructor @AllArgsConstructor public class UserInfoID implements Serializable {private String name, telephone; }
第二步:新建一个UserInfo实体,采用@IdClass引用联合主键
@Entity @Data @Builder @IdClass(UserInfoID.class) @NoArgsConstructor @AllArgsConstructor public class UserInfo {private Integer ages; @Idprivate String name;@Idprivate String telephone; }
第三步:新建一个UserInfoRepsitory类完成CRUD
@Repository public interface UserInfoRepository extends JpaRepository< UserInfo,UserInfoID> { }
第四步:写一个测试
@SpringBootTest class SpringDataJpaTestApplicationTests { @Resourceprivate UserInfoRepository userInfoRepository; @Testpublic void testIdClass() {userInfoRepository.save(UserInfo.builder().ages(29).name("sunfeng").telephone("18854885488").build()); Optional<UserInfo> userInfoOptional = userInfoRepository.findById(UserInfoID.builder().name("sunfeng").telephone("18854885488").build()); userInfoOptional.ifPresent(System.out::println);} }
通过上面的例子可以发现表的主键是primary key(name, telephone),而Entity里面不是一个@Id字段了
2、@Embeddable与@EmbedDedId注解使用
第一步:我们在上面的例子中的UserInfoID里面添加@Embeddable注解
@Data @Builder @NoArgsConstructor @AllArgsConstructor @Embeddable public class UserInfoID implements Serializable {private String name, telephone; }
第二步:修改一下我们刚才的UserInfo对象,删除@IdClass添加 @EmbeddedId注解
@Entity @Data @Builder @NoArgsConstructor @AllArgsConstructor public class UserInfo {private Integer ages; @EmbeddedIdprivate UserInfoID userInfoID;}
第三部:其他不变我们修改一下测试用例
@SpringBootTest class SpringDataJpaTestApplicationTests { @Resourceprivate UserInfoRepository userInfoRepository; @Testpublic void testIdClass() {userInfoRepository.save(UserInfo.builder().ages(29).userInfoID(UserInfoID.builder().name("sunfeng").telephone("18854885488").build()).build()); Optional<UserInfo> userInfoOptional = userInfoRepository.findById(UserInfoID.builder().name("sunfeng").telephone("18854885488").build()); userInfoOptional.ifPresent(System.out::println);}
运行完之后,可以得到相同的结果。那么两种方式之间的区别是什么?
-
在使用的时候 @EmbeddedId使用的是对象,而IdClass用的是具体的字段
-
二者的JPQL也会不一样
-
@IdClass的JPQL写法是:SELECT u.name FROM UserIndo u
-
@EmbeddedId的JPQL写法是:select u.userInfo.name FROM UserInfo u
-