Spring Hibernate JPA 规范

3

我可以为您翻译以下内容:

我有一个实体:

@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 Specification类来根据其属性过滤交易。

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

但是似乎没有返回任何内容。您有什么关于我做错了什么的想法吗?


你有没有想过查看由JPA Criteria查询生成的SQL语句? - Neil Stockton
2个回答

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

0
你正在正确构建“predicates”列表,但是在返回的谓词中没有使用它。相反,你正在返回builder.isTrue(propertiesRoot.in(criteria)),这毫无意义。你应该改成:
return builder.and(predicates.toArray(new Predicates[predicates.size()]))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接