36

我想使用 CriteriaBuilder 查询我加入 2 个表的位置。在 MySQL 中,我尝试进行的查询如下所示:

SELECT * FROM order
LEFT JOIN item
ON order.id = item.order_id
AND item.type_id = 1

我想获得所有订单,如果他们有 #1 类型的项目,我想加入这个项目。但是,如果没有找到 #1 类型的项目,我仍然想获得订单。我不知道如何用 CriteriaBuilder 来做这个。我所知道的只是:

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Order> cq = cb.createQuery(Order.class);
Root<Order> order = cq.from(Order.class);
Join<Order, Item> item = order.join(Order_.itemList, JoinType.LEFT);
Join<Item, Type> type = order.join(Item_.type, JoinType.LEFT);
cq.select(order);
cq.where(cb.equal(type.get(Type_.id), 1));

这个查询被破坏了,因为它在 MySQL 中产生了这样的结果:

SELECT * FROM order
LEFT JOIN item
ON order.id = item.order_id
WHERE item.type_id = 1

结果将仅包含类型为#1 的订单。没有的订单被排除在外。如何使用 CriteriaBuilder 创建第一个示例中的查询?

4

5 回答 5

38

可以使用方法2.1JPA的版本开始onJoin<Z, X> on(Predicate... restrictions);

方法如下:

Root<Order> order = cq.from(Order.class);
Join<Order, Item> item = order.join(Order_.itemList, JoinType.LEFT);
item.on(cb.equal(item.get(Item_.type), 1));
于 2016-06-23T14:03:15.670 回答
2

我认为这与这个问题中提出的问题相同。看起来在 CriteriaBuilder 中是不可能的。在 Hibernate Criteria API 中是可能的,但这可能对您没有帮助。

JPA Criteria API:LEFT JOIN 上的多个条件

于 2013-04-14T13:57:17.233 回答
0

我知道这个问题已经提出了很长时间,但最近遇到了同样的问题,我从 Oracle 论坛找到了这个解决方案,我复制并粘贴了以防万一链接不再可用。

MiguelChillitupaArmijos 29-abr-2011 1:41 (en respuesta a 840578) 认为你应该使用类似的东西:

em.createQuery("SELECT DISTINCT e.Id" +
                    " from Email e " +
                    " left join e.idEmailIn e2 *with* e2.responseType = 'response'" +
                    "     where e.type = 'in' and e.responseMandatory = true").getSingleResult(); 

这是链接。

JPA 标准:带有 AND 条件的 LEFT JOIN

于 2015-05-28T18:52:52.833 回答
0

如果您将 Hibernate 3.6 与 JPA 2.0 一起使用,则有一个解决方法。这不是更好的解决方案,但它对我来说非常完美。

我已经用@Where hibernate 注释复制了实体。这意味着每次你使用这个实体的连接时,hibernate 都会在生成的 SQL 的连接语句上添加额外的条件。

例如,最初我们有以下示例:

@Entity
@Table(name = "PERSON")
public class Person {

    @Id
    @Column(name = "PERSON_ID")
    private Long id;

    @Id
    @Column(name = "PERSON_NAME")
    private String name;

   @OneToMany(mappedBy = "person", fetch = FetchType.LAZY)
   private Set<Address> addresses;

}

@Entity
@Table(name = "ADDRESS")
public class Address {

    @Id
    @Column(name = "ADDRESS_ID")
    private Long id;

    @Id
    @Column(name = "ADDRESS_STREET")
    private String street;

   @ManyToOne
   @JoinColumn(name = "PERSON_ID")
    private Person person;

}

为了在条件加入上添加额外的条件,我们需要复制地址 @Entity 映射,添加 @Where 注释 @Where(clause = "ADDRESS_TYPE_ID = 2")。

@Entity
@Table(name = "ADDRESS")
@Where(clause = " ADDRESS_TYPE_ID = 2")
public class ShippingAddress {

    @Id
    @Column(name = "ADDRESS_ID")
    private Long id;

    @Id
    @Column(name = "ADDRESS_STREET")
    private String street;

   @OneToOne
   @JoinColumn(name = "PERSON_ID")
    private Person person;

}

此外,我们需要为新实体添加重复映射关联。

@Entity
@Table(name = "PERSON")
public class Person {

    @Id
    @Column(name = "PERSON_ID")
    private Long id;

    @Id
    @Column(name = "PERSON_NAME")
    private String name;

   @OneToMany(mappedBy = "person", fetch = FetchType.LAZY)
   private Set<Address> addresses;

   @OneToOne(mappedBy = "person")
   private ShippingAddress shippingAddress;

}

最后,您可以在您的条件中使用与此特定实体的联接:

PersonRoot.join(Person_.shippingAddress, JoinType.LEFT);

Hibernate Snippet SQL 应该是这样的:

 left outer join
        address shippingadd13_ 
            on person11_.person_id=shippingadd13_.person_id 
            and (
                shippingadd13_.ADDRESS_TYPE_ID = 2 
            ) 
于 2015-06-29T22:07:20.750 回答
0

在 Hibernate 4.3 版本中支持 ON 子句,任何人都知道在使用 ON 子句进行外部联接时,附加自定义条件的参数索引与现有映射过滤器的索引之间是否存在参数索引问题?

以下面的 Person 实体类为例,假设我正在添加此过滤器以限制地址类型,并且启用过滤器以填充 IN 子句。当我在 ON 子句中添加附加条件(例如使用 'street' 列)时,IN 子句的参数索引将导致问题 [2]。是已知问题吗?

[1] @Filter(name = "addressTypes", condition = "ADDRESS_TYPE in (:supportedTypes)")

[2] 原因:错误 22018:BIGINT 类型的字符串格式无效。私人设置地址;

于 2016-11-29T21:10:40.117 回答