JPA联合主键

​ 在实际工作中,我们会经常遇到联合主键的情况,所以我用简单例子列举JPA两种实现联合主键的方式。

1、如何通过@IdClass 实现联合主键

第一步:新建一个UserInfoID类,里面是联合主键

java 复制代码
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserInfoID implements Serializable {
    private String name, telephone;
}

第二步:新建一个UserInfo实体,采用@IdClass引用联合主键

java 复制代码
@Entity
@Data
@Builder
@IdClass(UserInfoID.class)
@NoArgsConstructor
@AllArgsConstructor
public class UserInfo {
    private Integer ages;

    @Id
    private String name;
    @Id
    private String telephone;
}

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

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

第四步:写一个测试

java 复制代码
@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注解

java 复制代码
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Embeddable
public class UserInfoID implements Serializable {
    private String name, telephone;
}

第二步:修改一下我们刚才的UserInfo对象,删除@IdClass添加 @EmbeddedId注解

java 复制代码
@Entity
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserInfo {
    private Integer ages;

    @EmbeddedId
    private UserInfoID userInfoID;
    
}

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

java 复制代码
@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
相关推荐
学计算机的计算基24 分钟前
操作系统内存管理全解:虚拟内存、页表、COW、malloc、OOM一篇搞定
java·笔记·算法
tachibana228 分钟前
hot100 前 K 个高频元素(347)
java·数据结构·算法·leetcode
万亿少女的梦1681 小时前
基于Spring Boot、Java与MySQL的网络订餐系统设计与实现
java·spring boot·mysql·系统设计·网络订餐
咩咩啃树皮9 小时前
第40篇:Vue3组件化开发精讲——组件拆分、复用、父子通信、工程化架构
java·前端·架构
鱟鲥鳚10 小时前
Spring Boot 集成 LangChain4j:从模型调用到 Tool Calling(Demo版)
java·spring boot
大模型码小白11 小时前
【Python零基础教程】继承、多态与魔法函数:面向对象编程三大核心特性详解
java·大数据·开发语言·人工智能·python·ai编程
腾渊信息科技公司12 小时前
Spring Boot对接MES实战:视觉检测数据自动同步方案
java·人工智能·spring boot·后端·计算机视觉·ai·软件需求
爱笑的源码基地13 小时前
高并发 Redis 缓存门诊HIS系统源码,含财务统计药房进销存
java·程序·门诊系统·诊所系统·云诊所源码
wuqingshun31415913 小时前
TCP超时重传机制是为了解决什么问题?
java
莫逸风15 小时前
【AgentScope 2.0】 0. 学习指南
java·llm·agent·agentscope