在实际工作中,我们会经常遇到联合主键的情况,所以我用简单例子列举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;@Idprivate String name;@Idprivate String telephone;
}
第三步:新建一个UserInfoRepsitory类完成CRUD
@Repository
public interface UserInfoRepository extends JpaRepository< UserInfo,UserInfoID> {
}
第四步:写一个测试
@SpringBootTest
class SpringDataJpaTestApplicationTests {@Resourceprivate UserInfoRepository userInfoRepository;@Testpublic 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;@EmbeddedIdprivate UserInfoID userInfoID;}
第三部:其他不变我们修改一下测试用例
@SpringBootTest
class SpringDataJpaTestApplicationTests {@Resourceprivate UserInfoRepository userInfoRepository;@Testpublic 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