【问题标题】:Criteria hibernate join条件休眠加入
【发布时间】:2019-02-19 10:52:18
【问题描述】:

我需要做一个返回“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();

我总是得到一个列表,我不知道如何获得列表。这可能吗?

编辑:使用 Java SE 1.7

【问题讨论】:

  • 如果您想要Bs 的列表,您需要A 做什么?
  • 到其他子句,例如 criteria.add(Restrictions.eq("b.name", "some name"));

标签: java hibernate criteria


【解决方案1】:

如果您不希望 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());
}

【讨论】:

  • 对不起,我忘了说我使用的是 Java SE 1.7,并得到错误“方法引用只允许在源级别 1.8 或更高版本”
  • 不是我想要的,但它很有用。谢谢!
  • 尝试编辑您的问题,使其更具体,以便我为您提供帮助
【解决方案2】:

您可以使用这样的嵌套条件导航到关联:

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();

一开始这似乎非常繁重和复杂,但可以非常动态地使用它,因为您可以从 sn-p 中提取多个方法并启用添加多个 where 条件、排序依据、分组依据等。

【讨论】:

    【解决方案3】:

    最后我做到了:

    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();
    }
    

    子查询因为将在数据库中占用很少的记录。 感谢您的帮助!

    【讨论】:

      猜你喜欢
      • 2014-09-04
      • 1970-01-01
      • 1970-01-01
      • 2023-04-11
      • 1970-01-01
      • 2013-11-03
      • 2016-03-15
      • 1970-01-01
      相关资源
      最近更新 更多