How to make a CriteriaBuilder join with a custom “on” condition?

こ雲淡風輕ζ 提交于 2019-11-28 23:10:57

It is possible using the on method Join<Z, X> on(Predicate... restrictions);

Here is how:

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

I think this is the same problem as posed in this question. It looks like it is not possible in CriteriaBuilder. It is possible in Hibernate Criteria API, but that probably won't help you.

JPA Criteria API: Multiple condition on LEFT JOIN

I know this question was made a long time a go, but recently a had the same problem and i found this solution from an Oracle forum, i copied and pasted just in case the link is not longer available.

MiguelChillitupaArmijos 29-abr-2011 1:41 (en respuesta a 840578) Think you should use something like:

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

An this is the link.

JPA Criteria : LEFT JOIN with an AND condition

There is a workaround if you are using Hibernate 3.6 with JPA 2.0 It is not the better solution, however it works perfect for me.

I´ve duplicate the entity with the @Where hibernate annotation.It means that everytime you use the join with this entity, hibernate will add the extra condition on the join statement at generated SQL.

For instance, initially we have the follow example:

@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;

}

In order to add extra conditions on criteria Join, we need duplicate the Address @Entity mapping , adding the @Where annotation @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;

}

Also, we need to add the duplicate mapping association for the new entity.

@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;

}

Finally, you can use a join with this specific Entity in your criteria :

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

The Hibernate Snippet SQL should seems like this :

 left outer join
        address shippingadd13_ 
            on person11_.person_id=shippingadd13_.person_id 
            and (
                shippingadd13_.ADDRESS_TYPE_ID = 2 
            ) 

ON clause is supported in Hibernate 4.3 version, anyone is aware if there is a parameter indexing issue between the parameter index of the additional custom conditions with the index of the existing mapping filters when doing an outer join with ON clause?

Using the Person entity class below as an example, say I am adding this filter to limit the address types and the filter is enabled to populate the IN clause. The parameter index for the IN clause will cause the issue [2] when I add additional conditions (such as using 'street' column) part of the ON clause. Is is a known issue?

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

[2] Caused by: ERROR 22018: Invalid character string format for type BIGINT. private Set addresses;

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!