在实际工作中,我们会经常遇到联合主键的情况,所以我用简单例子列举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);
}
运行完之后,可以得到相同的结果。那么两种方式之间的区别是什么?
-
在使用的时候 @EmbeddedId使用的是对象,而IdClass用的是具体的字段
-
二者的JPQL也会不一样
-
@IdClass的JPQL写法是:SELECT u.name FROM UserIndo u
-
@EmbeddedId的JPQL写法是:select u.userInfo.name FROM UserInfo u
-