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

相关推荐
cmpxr_10 分钟前
【C】局部变量和全局变量及同名情况
c语言·开发语言
小碗羊肉1 小时前
【从零开始学Java | 第三十一篇下】Stream流
java·开发语言
❀͜͡傀儡师1 小时前
Spring AI Alibaba vs. AgentScope:两个阿里AI框架,如何选择?
java·人工智能·spring
aq55356001 小时前
Laravel10.x重磅升级,新特性一览
android·java·开发语言
一 乐2 小时前
酒店预订|基于springboot + vue酒店预订系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·酒店预订系统
报错小能手2 小时前
ios开发方向——swift错误处理:do/try/catch、Result、throws
开发语言·学习·ios·swift
Moe4882 小时前
Spring AI Advisors:从链式增强到递归顾问
java·后端
敖正炀2 小时前
ReentrantReadWriteLock、ReentrantLock、synchronized 对比
java
网域小星球2 小时前
C 语言从 0 入门(十七)|结构体指针 + 动态内存 + 文件综合实战
c语言·开发语言·文件操作·结构体指针·动态内存·综合项目
cike_y2 小时前
Java反序列化漏洞-Shiro721流程分析
java·反序列化·shiro框架