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;
​
    @Id
    private String name;
    @Id
    private String telephone;
}
​

第三步:新建一个UserInfoRepsitory类完成CRUD

复制代码
@Repository
public interface UserInfoRepository  extends JpaRepository< UserInfo,UserInfoID> {
}
​

第四步:写一个测试

复制代码
@SpringBootTest
class SpringDataJpaTestApplicationTests {
​
​
    @Resource
    private UserInfoRepository userInfoRepository;
​
    @Test
    public 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;
​
    @EmbeddedId
    private UserInfoID userInfoID;
    
}
​

第三部:其他不变我们修改一下测试用例

复制代码
​
@SpringBootTest
class SpringDataJpaTestApplicationTests {
​
​
    @Resource
    private UserInfoRepository userInfoRepository;
​
    @Test
    public 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);
    }

运行完之后,可以得到相同的结果。那么两种方式之间的区别是什么?

  1. 在使用的时候 @EmbeddedId使用的是对象,而IdClass用的是具体的字段

  2. 二者的JPQL也会不一样

    1. @IdClass的JPQL写法是:SELECT u.name FROM UserIndo u

    2. @EmbeddedId的JPQL写法是:select u.userInfo.name FROM UserInfo u

相关推荐
小徐Chao努力3 分钟前
Spring AI Alibaba A2A 使用指南
java·人工智能·spring boot·spring·spring cloud·agent·a2a
梅孔立11 分钟前
【实用教程】python 批量解析 EML 邮件文件 存成txt ,可以利用 AI 辅助快速生成年终总结
开发语言·python
rannn_11113 分钟前
【Git教程】概述、常用命令、Git-IDEA集成
java·git·后端·intellij-idea
我家领养了个白胖胖13 分钟前
向量化和向量数据库redisstack使用
java·后端·ai编程
c#上位机22 分钟前
C#异步编程之async、await
开发语言·c#
苹果醋324 分钟前
Java设计模式实战:从面向对象原则到架构设计的最佳实践
java·运维·spring boot·mysql·nginx
郑州光合科技余经理34 分钟前
实战分享:如何构建东南亚高并发跑腿配送系统
java·开发语言·javascript·spring cloud·uni-app·c#·php
爱装代码的小瓶子35 分钟前
【c++进阶】C++11新特性:一切皆可{}初始化
开发语言·c++·visual studio
yaoxin52112338 分钟前
273. Java Stream API - Stream 中的中间操作:Mapping 操作详解
java·开发语言·python
技术小甜甜39 分钟前
[Python实战] 告别浏览器驱动烦恼:用 Playwright 优雅实现网页自动化
开发语言·python·自动化