我想使用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创建第一个示例中的查询?
答案 0 :(得分:14)
可以使用on
方法Join<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));
答案 1 :(得分:1)
我认为这与此问题中提出的问题相同。看起来在CriteriaBuilder中是不可能的。它可以在Hibernate Criteria API中使用,但这可能对您没有帮助。
答案 2 :(得分: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();
这是链接。
答案 3 :(得分:0)
如果您使用带有JPA 2.0的Hibernate 3.6,则有一种解决方法 这不是更好的解决方案,但它对我来说非常适合。
我已经使用@Where hibernate annotation复制了实体。这意味着每次你使用这个实体的连接时,hibernate都会在生成的SQL的join语句中添加额外的条件。
例如,最初我们有以下示例:
@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;
}
为了在条件Join上添加额外条件,我们需要复制Address @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
)
答案 4 :(得分:0)
ON子句,任何人都知道在使用ON子句进行外连接时,附加自定义条件的参数索引与现有映射过滤器的索引之间是否存在参数索引问题?
使用下面的Person实体类作为示例,假设我添加此过滤器以限制地址类型,并且启用过滤器以填充IN子句。当我添加ON子句的附加条件(例如使用'street'列)部分时,IN子句的参数索引将导致问题[2]。这是一个众所周知的问题吗?
[1] @Filter(name =“addressTypes”,condition =“ADDRESS_TYPE in(:supportedTypes)”)
[2] 引发者:ERROR 22018:类型BIGINT的字符串格式无效。 私人集合地址;