[英]Spring JPA using Specifications and CriteriaQuery on Joint Tables
我正在使用JPA规范和CriteriaQuery来向我的实体添加where子句。
域类:
public class Domain {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(name = "account_id")
private Long accountId;
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "domain_id")
private List<Notification> notification;
}
通知类别:
public class Notification {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(name = "domain_id")
private Long domainId;
@Column(name = "contact")
private String contact;
}
然后,我有以下用于创建规范的类:
public class DomainSpecification implements Specification<Domain> {
final private SearchCriteria criteria;
public DomainSpecification(SearchCriteria searchCriteria) {
this.criteria = searchCriteria;
}
@Override
public Predicate toPredicate(
Root<Domain> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
switch (criteria.getOperation()) {
case ":":
if (root.get(criteria.getKey()).getJavaType() == String.class) {
return builder.like(
root.<String>get(criteria.getKey()),
"%" + criteria.getValue() + "%");
} else {
return builder.equal(root.get(criteria.getKey()),
criteria.getValue());
}
case "=":
return builder.equal(root.get(criteria.getKey()),
criteria.getValue());
default:
return null;
}
}
}
和SearchCriteria对象:
public class SearchCriteria {
private final String key;
private final String operation;
private final Object value;
public SearchCriteria(String key, String operation, Object value) {
this.key = key;
this.operation = operation;
this.value = value;
}
public String getKey() {
return key;
}
public String getOperation() {
return operation;
}
public Object getValue() {
return value;
}
}
然后,每当我要创建where子句时,请执行以下操作:
DomainSpecification idSpecification
= new DomainSpecification(
new SearchCriteria("id", "=", domainId));
Specifications<Domain> specifications = Specifications.where(idSpecification);
final Domain domain = this.domainRepository.findOne(specifications);
这将通过域实体中名为id
的字段进行搜索。
现在,我如何也可以按加入的实体进行过滤? 例如,我要过滤Domain.id = 10和Notification.contact =“ abc”的位置?
谢谢你的帮助
您可以将Specification
的定义包装到帮助器类中:
public class DelegationSpecificationsHelper {
public static Specification<Domain> notificationContactSpec(String contact) {
return (root, query, cb) -> cb.equal(root.join("notification").get("contact"), contact);
}
public static Specification<Domain> idSpec(SearchCriteria searchCriteria) {
switch (criteria.getOperation()) {
case ":":
if (root.get(criteria.getKey()).getJavaType() == String.class) {
return builder.like(
root.<String>get(criteria.getKey()),
"%" + criteria.getValue() + "%");
} else {
return builder.equal(root.get(criteria.getKey()),
criteria.getValue());
}
case "=":
return builder.equal(root.get(criteria.getKey()),
criteria.getValue());
default:
return null;
}
}
}
然后您可以像这样使用它:
Specifications<Domain> specifications = Specifications.where(DelegationSpecificationsHelper.idSpec(new SearchCriteria("id", "=", domainId))
.and(DelegationSpecificationsHelper.notificationContactSpec("someSearchString"));
静态导入和一些重构后:
SearchCriteria idCriteria = new SearchCriteria("id", "=", domainId)
Specifications<Domain> specifications =
Specifications.where(idSpec(idCriteria)
.and(notificationContactSpec("someSearchString"));
当然,您应该从这里摆脱硬编码的值: cb.equal(root.join("notification").get("contact"), contact);
并改用一些DTO对象或生成的JPA元模型。
添加元模型后,它可能如下所示:
public static Specification<Domain> notificationContactSpec(String contactValue) {
return (root, query, cb) -> cb.equal(root.join(Domain_.notification).get(Notification_.contact), contactValue);
}
有关元模型生成的更多信息: https : //docs.jboss.org/hibernate/orm/5.0/topical/html/metamodelgen/MetamodelGenerator.html
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.