[英]Criteria hibernate join
我需要执行一个返回“ b”对象列表的条件。 我有以下课程:
---
A
---
private BigDecimal id;
private String name;
private B b;
---
B
---
private BigDecimal id;
private String name;
我这样做:
Criteria criteria = getSession().createCriteria(A.class,"a").createCriteria("b");
return criteria.list();
我总是得到一个List <A>,我不知道如何得到List <B>。 有可能吗
编辑:使用Java SE 1.7
如果您不希望A和B之间存在双向关系,请使用别名,然后仅收集b属性。
List<A> aList = getSession().createCriteria(A.class, "a")
.createAlias("a.b", "b")
.add(Restrictions.eq("a.name", "A name")
.add(Restrictions.eq("b.name", "B name")
.list();
List<B> bList = new ArrayList<>(aList.size());
for (A a : aList) {
bList.add(a.getB());
}
您可以使用嵌套的条件导航到关联,如下所示:
List<B> result = session.createCriteria( A.class )
.add( Restrictions.like("name","he%") )
.createCriteria( "b" )
.add( Restrictions.like("name", "he%") )
.list();
我的“第二个”答案不是针对Criteria,而是针对CriteriaBuilder ,对于小用例,我不建议使用它,而是针对需要动态创建查询,且用户或其他应用程序的条件不断变化的用例。
final CriteriaBuilder queryBuilder = getCriteriaBuilder(); // Retrieve your CriteriaBuilder here. I inject mine over CDI for example...
final CriteriaQuery<B> query = queryBuilder.createQuery( B.class ); // Type the query to it's expected end result type.
final Root<A> queryRoot = query.from( A.class ); // Select the root of the query
final Join<Object, Object> BJoin= queryRoot.join("b", JoinType.LEFT ); // "b" is the field name to use for the mapping between the root table to the joined table. In this case a.b
// The above equals "left join b on b.id = a.b.id "
// Perform a select with the Class resulting from the select and what wants to be selected.
// It is also possible to select only a field of a table but in our case we want the whole table of B to be selected.
final Selection<B> select = queryBuilder.construct( B.class, BJoin );
query.select(select); // add the select to the query
// We need to remember the ParameterExpression in order to fill the where condition.
// This acts as a typed(!) blank to later fill with the condition we want to match
final ParameterExpression<String> bName = queryBuilder.parameter(String.class);
// Define the where condition using the Path<T> you retrieve from Root or Join objects.
// This will make hibernate build the condition for the correct table like b.name
final Predicate bPredicate = queryBuilder.equal( bJoin.get("name"),bName );
query.where(bPredicate); // add the where expression to the query.
// The above equals something like "where b.name = ?"
// Compile the built query to a TypedQuery
// The EntitiyManager is also injected over CDI in my usual case.
final TypedQuery<B> builtQuery = javax.persistence.EntityManager.createQuery(query);
builtQuery.setParameter(bName,"test"); // Fill in the ? of the where condition.
final List<B> resultList = builtQuery.getResultList();
一开始这似乎很繁琐,但可以非常动态地使用它,因为您可以从代码段中提取多种方法,并允许添加多个where条件,order by,group by等。
最后,我做到了:
public List<B> findXXXX(A a) {
// A
DetachedCriteria aCriteria = DetachedCriteria.forClass(A.class, "a");
aCriteria.add(Restrictions.eq("a.name", "some name"));
aCriteria.setProjection(Projections.property("a.key"));
// B
Criteria bcriteria = getSession().createCriteria(B.class, "b");
bcriteria.add(Property.forName("a.key").in(aCriteria));
return bcriteria.list();
}
子查询,因为它将占用数据库中的很少记录。 感谢您的帮助!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.