代码示例:
@Entity
public class Event {
@Id
@GeneratedValue
private Long id;
private String name;
@OneToMany(mappedBy="event")
private List<Actions> actions;
}
@Entity
public class Action {
@Id
@GeneratedValue
private Long id;
private String name;
private Date date;
@ManyToOne
@JoinColumn(name = "event_id")
private Event event;
}
public class EventSpecification {
public static Specification<Event> findByCriteria(EventSearchCriteria criteria) {
return (root, criteriaQuery, criteriaBuilder) -> {
List<Predicate> predicates = new ArrayList<>();
criteria.getDate().ifPresent(date -> {
Join<Event, Action> join = root.join(Event_.actions);
predicates.add(criteriaBuilder.equal(join.get(Action_.date), criteria.getDate().get()));
});
return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
};
}
}
...
eventRepository.findAll(EventSpecification.findByCriteria(searchCriteria))
在我的数据库中,我有下一个:
Event Table
id, name
1, 'event_1'
2, 'event_2'
Action Table
id, name, date, event_id
1, 'action_event_1_1', '01-01-2018', 1
2, 'action_event_1_2', '01-01-2018', 1
3, 'action_event_1_3', '01-02-2018', 1
4, 'action_event_2_1', '01-03-2018', 2
将我的规范代码与data =&#39; 01-01-2018&#39;一起使用,结果我获得了相同Event对象的列表,列表的大小是已连接对象的数量,克劳斯Action.date = criteria.date:
[{id=1, name=event_1, actions=[all 3 actions]},
{id=1, name=event_1, actions=[all 3 actions]}]
我需要得到下一个结果:
{id=1, name=event_1, actions=[only two actions with date '01-01-2018']}
我尝试添加
criteriaQuery.groupBy(root.get(Event.id));
它修复了结果列表大小 -
{id=1, name=event_1, actions=[all 3 actions]}
但我仍然得到了事件1的所有3个动作。
问题是:
是否可以只获取包含具有所需日期的操作的事件,以便每个事件仅包含一个包含所请求日期的操作的列表?
答案 0 :(得分:1)
我找到了下一个解决方案:
public static Specification<Event> findByCriteria(EventSearchCriteriacriteria) {
return (root, criteriaQuery, criteriaBuilder) -> {
List<Predicate> predicates = new ArrayList<>();
criteria.getDate().ifPresent(date -> {
criteriaQuery.distinct(true);
Join<Event, Action> join = (Join<Event, Action>)root.fetch(Event_.actions);
predicates.add(criteriaBuilder.equal(join.get(Action_.date), criteria.getDate().get()));
});
return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
};
}
可能Join<Event, Action> join = (Join<Event, Action>)root.fetch(Event_.actions);
可能不是最佳解决方案,因为我的IDE会警告我关于转换,但这是我找到的唯一可行解决方案。
顺便说一下,如果不使用Criteria API,它的工作原理很完美:
@EntityGraph(value = "Event.actions", type = EntityGraph.EntityGraphType.LOAD)
@Query("select distinct e from Event e join e.actions a where a.date = (:date)")
List<Event> findAllWithActionsByDate(@Param("date") Date date);
但在我的案例中,避免使用Criteria API是不合适的。
答案 1 :(得分:0)
试试这个JPQL查询:
select e from Events e join Actions a with a.date=:date
group by e