2016-12-28 6 views
1

に参加し、私は次のクラスを抱えていると仮定します(極端に単純化)左春データJPAの仕様

@Entity 
@Table(name = "USER") 
public class User { 

    @OneToOne(mappedBy = "user", cascade = CascadeType.ALL) 
    private BillingAddress billingAddress; 

    @OneToOne(mappedBy = "user", cascade = CascadeType.ALL) 
    private ShippingAddress shippingAddress; // This one CAN be null 

} 

この抽象から*Address継承の両方:(再び、それは超単純化します)

春のブログ記事で説明したように
public abstract class Address { 

    @OneToOne(optional = false, fetch = FetchType.LAZY) 
    @JoinColumn(name = "USER_ID") 
    private User user; 

    @NotEmpty 
    @Size(max = 32) 
    @Column(name = "ADDR_TOWN") 
    private String town; 

} 

私は、JPAの仕様を試してみました:

/** 
* User specifications. 
* 
* @see <a href="https://spring.io/blog/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl">Advanced Spring Data JPA - Specifications and Querydsl</a> 
*/ 
public class UserSpecifications { 
    public static Specification<User> likeTown(String town) { 
     return new Specification<User>() { 
      @Override 
      public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) { 
       return cb.like(cb.lower(root.get("billingAddress").get("town")), '%' + StringUtils.lowerCase(town) + '%'); 
      } 
     }; 
    } 

次のように、この「仕様」の使用:

List<User> users = userRepository.findAll(UserSpecifications.likeTown(myTown)); 

しかし、今は、私はまた、存在しない可能性がありますのShippingAddress、のために町を検索したいです。 cb.orcb.likeの両方を結合しようとしましたが、上記のようにshippingAddressのINNER JOINが誤っているという結果になっていました。これは上記のようにnullかもしれないのでLEFT JOINです。

どうすればよいですか?

ありがとうございました。

答えて

0

役立つかどうかわかりません。

私は同じ問題を抱えていました。私が解決できる唯一の方法は、サブクエリを使用することでした。

predicate.and(subquery.exists()); 

NB:私は広範囲に仕様を使用していて私の場合はそれが助けた後、私は述語にサブクエリを追加使用

JPASubQuery subquery = new JPASubQuery(); 
subquery = subquery .from(/* tableB */); 
subquery .where(/* conditions */); 

例えば、これはそのような何かに似ているでしょう。ほとんどの場合、パフォーマンスへの影響はそれほど大きくはありませんでした。

EDIT: 私はちょうど私がquery-dslを使用しているとして、前者の例は、私の場合にのみ働いていたことに気づきました。

場合によっては、JPA 2.0, Criteria API, Subqueries, In Expressionsを参照してサブクエリーを作成し、それを述部条件に結合してください。

2

参加する指定タイプ:

town = '%' + StringUtils.lowerCase(town) + '%'; 
return cb.or(
    cb.like(cb.lower(root.join("billingAddress", JoinType.LEFT).get("town")), town), 
    cb.like(cb.lower(root.join("shippingAddress", JoinType.LEFT).get("town")), town)); 
関連する問題