Spring Hibernate JPA规范

时间:2016-01-06 19:25:17

标签: spring hibernate jpa spring-data-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", joinColumns=@JoinColumn(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));
  }
};

}

但这似乎没有任何回报。关于我做错了什么的任何想法?

2 个答案:

答案 0 :(得分:1)

尝试以下

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

答案 1 :(得分:0)

您正在构建predicates列表,但是您没有在返回的谓词中使用它。相反,你正在返回builder.isTrue(propertiesRoot.in(criteria))这没有任何意义。相反,你应该

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