我具有以下实体域。
父类
@Entity
public final class SupportModuleInteraction implements Serializable {
@Id
private Long id;
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "supportModuleInteraction")
@OrderColumn
private List<Event> events;
// ... getters/setters/ other attributes ommitted
}
儿童班级
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "event_type")
public abstract class Event implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@ManyToOne(fetch = FetchType.EAGER)
private SupportModuleInteraction supportModuleInteraction;
}
@Entity
@DiscriminatorValue("SEARCH")
public final class SearchEvent extends Event {
@Lob
private String searchTerm;
}
我正在尝试检索任何包含包含关键字的SearchEvent的SupportModuleInteractions。
这是我用来尝试检索那些SupportModuleInteractions的规范:
public static Specification<SupportModuleInteraction> interactionWithSearchEventContaingKeyword(String keyword) {
return new Specification<SupportModuleInteraction>() {
@Override
public Predicate toPredicate(Root<SupportModuleInteraction> smi, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
Join<SupportModuleInteraction, SearchEvent> events = smi.join("events");
return criteriaBuilder.and(
criteriaBuilder.equal(events.type(), SearchEvent.class),
criteriaBuilder.like(events.get("searchTerm"), "%" + keyword + "%"));
}
};
}
该规范未能说明Event不包含名为“ searchTerm”的属性,因为只有在SearchEvent子类中存在该属性,这才有意义。
我在这里JPA2 Criteria queries on entity hierarchy处查看了此答案,因为涉及查询的实体位于类层次结构之外,因此无法解决我的问题。
作为本机SQL查询,这就是我要达到的目标:
SELECT *
FROM event E JOIN support_module_interaction smi ON E.support_module_interaction_id = smi.id
WHERE event_type = 'SEARCH'
AND search_term LIKE 'searchString'
更新31/08/2019
我查看了JPA Criteria API: query property of subclass,并修改了规范以使用criteriaBuilder.treat(...)
,但没有运气:
public static Specification<SupportModuleInteraction> interactionWithSearchEventContaingKeyword(String keyword) {
return new Specification<SupportModuleInteraction>() {
@Override
public Predicate toPredicate(Root<SupportModuleInteraction> smi, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
Join<SupportModuleInteraction, SearchEvent> events = smi.join("events");
return criteriaBuilder.and(
criteriaBuilder.equal(events.type(), SearchEvent.class),
criteriaBuilder.like(
criteriaBuilder.treat(events.get("searchTerm"), SearchEvent.class).get("searchTerm"),
"%" + keyword + "%"));
}
};
}
答案 0 :(得分:0)
在JPA Crtieria API中很难使用Hibernate中的各种继承策略。
代替使用相当复杂的treat()
(请参阅HHH-9862和相关问题),生成一个subquery()
表达式来过滤searchTerm
并将其添加到您的父级中查询。
您的总体实现尚不清楚,因此我创建了一个基本示例:
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<SupportModuleInteraction> cq = cb.createQuery(SupportModuleInteraction.class);
Root<SupportModuleInteraction> supModIntRoot = cq.from(SupportModuleInteraction.class);
Join<SupportModuleInteraction, Event> supModIntEventJoin = supModIntRoot.join("events");
// Instantiate the Subquery and Root objects for your subclass entity
Subquery<SearchEvent> searchEventSubquery = cq.from(SearchEvent.class);
Root<SearchEvent> searchEventRoot = searchEventSubquery.from(SearchEvent.class);
// Generate the subquery and filter based on the given parameter
searchEventSubquery.select(searchEventRoot);
searchEventSubquery.where(cb.like(searchEventRoot.get("searchTerm", "%" + searchTerm + "%");
// add subquery to where clause in parent query
cq.select(supModIntRoot);
cq.where(supModIntEventJoin.in(searchEventSubquery), //other subqueries and filters...);