我有user
和user_related_user
个表以及User
JPA实体,
与自己有很多关系。
@Entity @Table(name = "user")
public class User implements Serializable {
@Id @GeneratedValue
private Long id;
@ManyToMany(cascade = {CascadeType.ALL})
@JoinTable(
name = "user_related_user",
joinColumns = {
@JoinColumn(name = "user_id", referencedColumnName = "id", nullable = false)
},
inverseJoinColumns = {
@JoinColumn(name = "related_user_id", referencedColumnName = "id", nullable = false)
}
)
public List<User> relatedUsers;
}
我想通过JPA规范从User#relatedUsers
获取User#id
。
所以我必须联合这个用户的相关用户&#34;和#34;更多用户&#34;动态。
在SQL中,需要以下查询。
SELECT u.id FROM user u WHERE u.id IN (
SELECT uru.related_user_id
FROM user_related_user uru
WHERE uru.user_id = ?
)
但我不知道如何使用JPA规范。 有谁知道更好的解决方案?
目前的解决方法是
@Repository
public interface UserRepository
extends JpaRepository<User, Long>, JpaSpecificationExecutor<User> {
@Query("select ru.id from User u join u.relatedUsers ru where u.id = ?1")
List<Long> findRelatedUserIds(Long id);
}
@Service @Transactional(readOnly = true)
public class UserService {
@Autowired
UserRepository repository;
public List<Users> getSelectableUsers(Long id, /* and args */) {
List<Long> currentRelatedUserIds = repository.findRelatedUserIds(id);
Specification<User> spec = (root, query, cb) -> {
return cb.or(
root.get(User_.id).in(currentRelatedUserIds),
/* generate some more predicates dynamically */
);
}
return repository.findAll(spec);
}
}
答案 0 :(得分:1)
如果我理解正确,您希望能够让相关用户找到用户。
我的输入数据是
insert into user values(1);
insert into user values(2);
insert into user values(3);
insert into user values(4);
insert into user values(5);
insert into user values(6);
insert into user values(7);
insert into user values(8);
insert into user values(9);
insert into user values(10);
insert into user_related_user values(1,10);
insert into user_related_user values(1,9);
insert into user_related_user values(1,8);
insert into user_related_user values(2,7);
insert into user_related_user values(2,6);
insert into user_related_user values(2,5);
我的存储库是
@Repository
public interface UserRepository
extends JpaRepository<User, Long>, JpaSpecificationExecutor<User> {
@Query("select ru.id from User u join u.relatedUsers ru where u.id = ?1")
List<Long> findRelatedUserIds(Long id);
List<User> findDistinctByRelatedUsersIdIn(List<Long> ids);
}
我的测试是
List<User> selectableUsers = userRepository.findDistinctByRelatedUsersIdIn(Arrays.asList(new Long[]{10l,9l,8l,7l,6l,5l}));
assertEquals(2, selectableUsers.size());
希望这有帮助。
答案 1 :(得分:0)
最后我通过使用SubQuery来解决这个问题。
public List<Users> getSelectableUsers(Long id, /* and args */) {
Specification<User> spec = (root, query, cb) -> {
query.distinct(true);
Subquery<User> sq = query.subquery(User.class);
Root<User> sqRoot = sq.from(User.class);
sq.select(
sqRoot.join(User_.relatedUsers)
).where(
cb.equal(sqRoot.get(User_.id), id)
);
return cb.or(
root.in(sq),
// some more dynamic condition
);
}
return repository.findAll(spec);
}