我想从Spring Data Specification执行子查询。它必须像这样的SQL语句:
select u from users u where u.name in (select up.username from users_profiles up where up.profile in ('admin'));
我有3个简单的表:
users
存储用户数据profiles
存储用户个人资料类型users_profiles
,可以消除用户和多个个人资料之间的关系因此,有了配置文件列表,我需要找到所有具有这些配置文件的用户。
public List<User> getUsersByProfileType(List<String> profileTypes) {
return userRepository.findAll(new Specification<User> () {
@Override
public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
final List<Predicate> predicates = new ArrayList<>();
/*
userNamesWithMatchedProfiles = select up.username from users_profiles up where up.profile in profileTypes
*/
List<String> userNamesWithMatchedProfiles = new ArrayList<String>();
predicates.add(root.get("name").in(userNamesWithMatchedProfiles))
return cb.and(predicates.toArray(new Predicate[predicates.size()]));
}
});
}
答案 0 :(得分:0)
您应该使用Java Persistence Query Language (JPQL).
总而言之,指定一个@NamedQuery
来执行数据库查询...
@Entity
@NamedQuery(name="User.findAdmins", query="SELECT u FROM User u WHERE u.name IN (SELECT up.username FROM UserProfile up WHERE up.profile IN ('admin')")
public class User extends Serializable...
...然后在您的代码中执行它:
List<String> userNamesWithMatchedProfiles =
entityManager.createNamedQuery("User.findAdmins").getResultList();
以上内容应大致提供 您所需的内容。您会注意到,语法类似于SQL,只有很小的区别。将SQL转换为JPQL非常简单。
您当然可以直接将其作为Query
执行,而无需将其存储为NamedQuery。我这样做是因为(以我的拙见)这是一种简洁的模式,有助于保持JPA逻辑井井有条。
请注意,您可以将参数注入查询中。例如:
@NamedQuery(name="User.findUser", query="SELECT u FROM User u WHERE u.name = :name")
...
List results = entityManager
.createNamedQuery("Profile.findUser")
.setParameter("name", "Daniel")
.getResultList();
答案 1 :(得分:0)
我找到了执行子查询的方法:
public List<User> getUsersByProfileType(List<String> profileTypes) {
return userRepository.findAll(new Specification<User> () {
@Override
public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
final List<Predicate> predicates = new ArrayList<>();
final Subquery<UserProfile> userProfileSubquery = query.subquery(UserProfile.class);
final Root<UserProfile> userProfile = userProfileSubquery.from(UserProfile.class);
// select up.username from users_profiles ...
userProfileSubquery.select(userProfile.get("user").get("name"));
// ... where up.profile in ('admin')
userProfileSubquery.where(cb.trim(userProfile.get("profile").get("id")).in(profileTypes));
// select u from users u where u.name in ...
predicates.add(root.get("name").in(userProfileSubquery));
return cb.and(predicates.toArray(new Predicate[predicates.size()]));
}
});
}
答案 2 :(得分:0)
使用Hibernate查询(本机),如下所示在UserRepository上,您也可以使用自定义参数。
3
objects
found #or
$counter objects found #or
$($counter) objects found