2017-06-07 12 views
0

私はちょうどSpecificationのオブジェクトとCriteria *オブジェクトで作業を始めました。単純な左結合を行い、値を結合されたエンティティプロパティの1つ。 ビルドしようとしているfind/select関数は遅かれ早かれ非常に動的になります。異なるパラメータで異なる関数を作成するのではなく、Criteriaオブジェクトで作業することにしました。 私の実際のエンティティはいくつかのプロパティを持っていますが、単純化するためにここに分割しました。Springデータ:仕様とJPA基準:コレクションプロパティの結合と検索/フィルタリングの方法

私は私の最初のステップSpecifificationを行うにしようとしていた前に私が@Queryで注釈されたと罰金働いていたリポジトリ機能だった。その後、私は下ケースを無視して仕様を構築しようとした

@Query("SELECT DISTINCT c FROM Competition c " + 
    "LEFT JOIN c.aliases a " + 
    "WHERE " + 
    "(lower(a.value) = :name OR lower(c.name) = :lowerCaseName) " + 
    "... and so on ") 

をし、 Competition名前とイムはまだ...これはAlias値プロパティで名パラメータを比較するための正しい加入行う方法で失敗

まずエンティティ:

@Entity 
public class Competition extends AbstractEntity { 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Long id; 

    @Column(nullable = false) 
    private String name; 

    @ManyToMany(cascade = CascadeType.MERGE) 
    @JoinTable(name="competition_name_alias", [email protected](name="competition_id"), [email protected](name="alias_id")) 
    private Set<Alias> aliases = new HashSet<>(); 

    ... 
} 

第二エンティティ:

@Entity 
public class Alias extends AbstractEntity { 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Long id; 

    @Column(unique = true) 
    private String value; 

    ... 
} 

仕様:

public static Specification<Competition> withLowerCaseName(String name) { 
    return new Specification<Competition>() { 
     @Override 
     public Predicate toPredicate(Root<Competition> product, CriteriaQuery<?> query, CriteriaBuilder builder) { 
      final List<Predicate> predicates = new ArrayList<Predicate>(); 

      Root<Competition> root = query.from(Competition.class); 

      Subquery<Alias> subquery = query.subquery(Alias.class); 
      SetJoin<Competition, Alias> aliases = root.join(Competition_.aliases); 

      Predicate predicate = builder.equal(aliases.get(Alias_.value), name); 
      builder.and(predicate); 

      Predicate[] predicatesArray = new Predicate[predicates.size()]; 

      query.distinct(true); 

      return builder.and(predicates.toArray(predicatesArray)); 
     } 
    }; 
} 

この機能を使用するには、私のすべての競技を取得し、nameパラメータを無視しているようです。 ハイバネートデバッグ/トレースロギングをオンにするとその理由が示されます。生成されたSQLには、唯一の条件として where 1=1があります。

descriptor.sql.BasicBinderパラメータのログに切り替えながら示さは名前値もありません...

誰がimが間違っている何のヒントを持っていますか?

答えて

0

非常に異なる例が見つかったhereと私の星座のためにそれを変更しました。仕事をしているようだ...

final Subquery<Alias> aliasSubquery = query.subquery(Alias.class); 
final Root<Alias> alias = aliasSubquery.from(Alias.class); 
final Expression<Set<Alias>> aliases = product.get(Competition_.aliases); 
aliasSubquery.select(alias); 
aliasSubquery.where(builder.equal(builder.lower(alias.get(Alias.value)), lowerCaseName), builder.isMember(alias, aliases)); 

builder.and(builder.exists(aliasSubquery)); 
関連する問題