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

相关推荐
Swift社区1 小时前
在 Swift 中实现字符串分割问题:以字典中的单词构造句子
开发语言·ios·swift
没头脑的ht1 小时前
Swift内存访问冲突
开发语言·ios·swift
没头脑的ht1 小时前
Swift闭包的本质
开发语言·ios·swift
wjs20241 小时前
Swift 数组
开发语言
吾日三省吾码2 小时前
JVM 性能调优
java
stm 学习ing2 小时前
FPGA 第十讲 避免latch的产生
c语言·开发语言·单片机·嵌入式硬件·fpga开发·fpga
湫ccc3 小时前
《Python基础》之字符串格式化输出
开发语言·python
弗拉唐3 小时前
springBoot,mp,ssm整合案例
java·spring boot·mybatis
oi773 小时前
使用itextpdf进行pdf模版填充中文文本时部分字不显示问题
java·服务器