Hibernate Criteria API @ElementCollection 上的子查询
Hibernate Criteria API Subquery on @ElementCollection
我已经搜索了很多,但无法正常工作。
我也发现了这个,它很接近但是它需要一个不必要的连接并且不能忽略区分大小写:
这是简化的实体:
@Entity(name = "Users")
public class User {
@Id
@Column(columnDefinition = "TEXT")
private String id;
@ElementCollection
@LazyCollection(LazyCollectionOption.FALSE)
private List<String> communities;
}
jpa/hibernate 魔术将其转换为两个表:users(text id) 和 users_communities(text id, text communities )
我想映射到条件的普通 sql 语句是:
select u.id from users u
where u.users_id not in (
select uc.users_id
from users_communities uc
where lower(communities) = 'test_user_app'
);
这是我当前的 java 代码。如何在 subJoin 上使用“criteriaBuilder.lower()”?没有更简单的方法吗?是否可以避免手动 subJoin?
Subquery<String> subquery = criteria.subquery(String.class);
Root<User> subRoot = subquery.from(User.class);
Join<Object, Object> subJoin = subRoot.join("communities");
subquery.select(subRoot.get("id"));
subquery.where(criteriaBuilder.equal(root.get("id"), subRoot.get("id")), subJoin.in("community_to_find"));
return criteriaBuilder.exists(subquery);
令人难以置信,花了我一整天......
如果不需要不区分大小写或类似表达式,最简单的方法是:
criteriaBuilder.isMember(
"community_to_find",
criteria.from(User.class).get("communities")
);
万一确实需要类似的表达式或不区分大小写:
目前似乎无法避免不必要的子连接!无论如何,这终于让我的测试再次变绿了 :-) :
Subquery<String> subquery = criteria.subquery(String.class);
Root<User> subRoot = subquery.from(User.class);
subquery.select(subRoot.get("id"));
subquery.where(criteriaBuilder.like(criteriaBuilder.lower(subRoot.join("communities")), argument));
return criteriaBuilder.in(root.get("id")).value(subquery);
提示:
您可能已经从外部查询定义了 Root,因为它是一个 ElementCollection,所以很可能是相同的 class。
在这种情况下,您可以通过以下方式定义更通用的 subRoot:
Root<? extends User> subRoot = subquery.from(root.getJavaType());
我已经搜索了很多,但无法正常工作。
我也发现了这个,它很接近但是它需要一个不必要的连接并且不能忽略区分大小写:
这是简化的实体:
@Entity(name = "Users")
public class User {
@Id
@Column(columnDefinition = "TEXT")
private String id;
@ElementCollection
@LazyCollection(LazyCollectionOption.FALSE)
private List<String> communities;
}
jpa/hibernate 魔术将其转换为两个表:users(text id) 和 users_communities(text id, text communities )
我想映射到条件的普通 sql 语句是:
select u.id from users u
where u.users_id not in (
select uc.users_id
from users_communities uc
where lower(communities) = 'test_user_app'
);
这是我当前的 java 代码。如何在 subJoin 上使用“criteriaBuilder.lower()”?没有更简单的方法吗?是否可以避免手动 subJoin?
Subquery<String> subquery = criteria.subquery(String.class);
Root<User> subRoot = subquery.from(User.class);
Join<Object, Object> subJoin = subRoot.join("communities");
subquery.select(subRoot.get("id"));
subquery.where(criteriaBuilder.equal(root.get("id"), subRoot.get("id")), subJoin.in("community_to_find"));
return criteriaBuilder.exists(subquery);
令人难以置信,花了我一整天...... 如果不需要不区分大小写或类似表达式,最简单的方法是:
criteriaBuilder.isMember(
"community_to_find",
criteria.from(User.class).get("communities")
);
万一确实需要类似的表达式或不区分大小写: 目前似乎无法避免不必要的子连接!无论如何,这终于让我的测试再次变绿了 :-) :
Subquery<String> subquery = criteria.subquery(String.class);
Root<User> subRoot = subquery.from(User.class);
subquery.select(subRoot.get("id"));
subquery.where(criteriaBuilder.like(criteriaBuilder.lower(subRoot.join("communities")), argument));
return criteriaBuilder.in(root.get("id")).value(subquery);
提示: 您可能已经从外部查询定义了 Root,因为它是一个 ElementCollection,所以很可能是相同的 class。 在这种情况下,您可以通过以下方式定义更通用的 subRoot:
Root<? extends User> subRoot = subquery.from(root.getJavaType());