2016-01-06 271 views
1

我有以下實體:春天Hibernate的JPA規範

@Entity 
public class Transaction implements java.io.Serializable { 
    private static final long serialVersionUID = 1L; 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    protected Long id; 

    @ElementCollection(fetch = FetchType.EAGER) 
    @CollectionTable(name="TRANSACTION_CONFIG", [email protected](name="TRANSACTION_ID")) 
    @MapKeyColumn(name = "PROPERTY_KEY") 
    @Column(name = "PROPERTY_VALUE") 
    protected Map<String, String> properties = new HashMap<String, String>(); 



    public Transaction() { 
    super(); 
    } 

    public Long getId() { 
    return id; 
    } 

    public void setId(Long id) { 
    this.id = id; 
    } 


    public Map<String, String> getProperties() { 
    return properties; 
    } 

    public void setProperties(Map<String, String> properties) { 
    this.properties = properties; 
    } 
} 

我想通過它的「屬性」,找到了交易。出於這個原因,我編寫了以下Spring規範類來通過其屬性過濾事務。

public static Specification<Transaction> matches(final Map<String, String> criteria) { 
return new Specification<Transaction>() { 
    @Override 
    public Predicate toPredicate(Root<Transaction> root, CriteriaQuery<?> query, 
     CriteriaBuilder builder) { 
    List<Predicate> predicates = new ArrayList<Predicate>(); 
    Path<Map<String, String>> propertiesRoot = root.join("properties"); 
    for (String key : criteria.keySet()) { 
     Predicate p = builder.and(propertiesRoot.in(key), propertiesRoot.in(criteria.get(key))); 
     predicates.add(p); 
    } 
    return builder.isTrue(propertiesRoot.in(criteria)); 
    } 
}; 

}

但這似乎並不返回任何東西。任何關於我在做什麼錯的想法?

+0

想過看着你的JPA標準查詢生成的SQL? –

回答

0

您正在構建正確的predicates列表,但是您沒有在要返回的謂詞中使用它。相反,你正在返回builder.isTrue(propertiesRoot.in(criteria))這是沒有意義的。相反,你應該

return builder.and(predicates.toArray(new Predicates[predicates.size()])) 
0

請嘗試以下

public static Specification<Transaction> matches(final Map<String, String> criteria) { 
    return new Specification<Transaction>() { 
     @Override 
     public Predicate toPredicate(Root<Transaction> root, CriteriaQuery<?> query, CriteriaBuilder builder) { 

      List<Predicate> predicates = new ArrayList<>(); 

      //you can define RIGHT or INNER join if you want 
      MapJoin<Transaction, String, String> propertiesRoot = root.joinMap("properties", JoinType.LEFT); 

      for (Map.Entry entry : criteria.entrySet()) { 
       Predicate predicate = builder.and(
        builder.equal(propertiesRoot.key(), entry.getKey()), 
        builder.equal(propertiesRoot.value(), entry.getValue()) 
       ); 
       predicates.add(predicate); 
      } 

      Predicate[] predicatesArray = predicates.toArray(new Predicate[predicates.size()]); 
      return builder.and(predicatesArray); 
     } 
    }; 
} 

或者,如果你正在使用Java8

public static Specification<Transaction> matches(final Map<String, String> criteria) { 
    return (root, query, builder) -> { 
     //you can define RIGHT or INNER join if you want 
     MapJoin<Transaction, String, String> propertiesRoot = root.joinMap("properties", JoinType.LEFT); 

     List<Predicate> predicates = criteria.entrySet().stream() 
      .map(entry -> 
       builder.and(
        builder.equal(propertiesRoot.key(), entry.getKey()), 
        builder.equal(propertiesRoot.value(), entry.getValue()) 
       )) 
      .collect(Collectors.toList()); 

     Predicate[] predicatesArray = predicates.toArray(new Predicate[predicates.size()]); 
     return builder.and(predicatesArray); 
    }; 
}