2

代码示例:

    @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='01-01-2018' 一起使用,结果我得到了一个相同事件对象的列表,并且列表的大小是连接对象的计数,它们满足子句 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 个动作。

问题是:

是否可以仅获取包含具有所需日期的操作的事件,并且每个事件仅包含一个包含具有请求日期的操作的列表?

4

2 回答 2

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 是不合适的。

于 2018-01-25T11:09:19.860 回答
0

试试这个 JPQL 查询:

select e from Events e join Actions a with a.date=:date
group by e
于 2018-01-25T03:57:23.933 回答