春天Hibernate的JPA规范
问题描述:
我有以下实体:春天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));
}
};
}
但这似乎并不返回任何东西。任何关于我在做什么错的想法?
答
您正在构建正确的predicates
列表,但是您没有在要返回的谓词中使用它。相反,你正在返回builder.isTrue(propertiesRoot.in(criteria))
这是没有意义的。相反,你应该
return builder.and(predicates.toArray(new Predicates[predicates.size()]))
答
请尝试以下
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);
};
}
想过看着你的JPA标准查询生成的SQL? –