为了账号安全,请及时绑定邮箱和手机立即绑定

JPA - 按对象集合中的多个属性查找

JPA - 按对象集合中的多个属性查找

慕盖茨4494581 2021-09-03 14:47:10
我有一个具有以下属性的事件对象:class Event {    String name;    String location;    LocalDateTime date;    String description;}假设我从 Web API 获得了一个事件列表:List<Events> events = getEvents(); // e.g. 5 events现在我想检查我的数据库中已经有多少这些事件。如果值的组合:名称、位置和日期也是唯一的,则事件是唯一的。所以基本上我想要一个创建查询来做到这一点:Optional<Event> getByNameAndLocationAndDate(String name, String location, LocalDate date);但是对于一个查询中的项目列表。就像是:Optional<Event> getByNameAndLocationAndDate(List<Events> events);JPA可以吗?
查看完整描述

2 回答

?
慕雪6442864

TA贡献1812条经验 获得超5个赞

没有内置的或特别漂亮的方法来做到这一点。但是您可以使用循环生成查询:


public List<Event> getByNameAndLocationAndDate(List<Event> events) {

    if (events.isEmpty()) {

        return new ArrayList<>();

    }

    final StringBuilder queryBuilder = new StringBuilder("select e from Event e where ");

    int i = 0;

    for (final Event event : events) {

        if (i > 0) {

            queryBuilder.append("or")

        } 

        queryBuilder.append(" (e.name = :name" + i);

        queryBuilder.append(" and e.location = :location" + i);

        queryBuilder.append(" and e.date = :date" + i + ") ");

        i++;

    }

    final TypedQuery<Event> query = em.createQuery(queryBuilder.toString());


    int j = 0;

    for (final Event event : events) {

        query.setParameter("name" + j, event.getName());

        query.setParameter("location" + j, event.getLocation());

        query.setParameter("date" + j, event.getDate());

    }

    return query.getResultList();

}

就像我说的,不是很漂亮。使用标准 API 可能会更好。再说一次,除非您对执行速度有非常严格的要求,否则最好一次遍历列表检查一个事件。这将导致对数据库运行更多的查询,但也会产生更漂亮的代码。


编辑:这是使用标准 API 的尝试,还没有使用它太多,所以只是通过谷歌搜索创建的,不能保证它按原样工作..


public List<Event> getByNameAndLocationAndDate(List<Event> events) {

    if (events.isEmpty()) {

        return new ArrayList<>();

    }

    final CriteriaBuilder cb = em.getCriteriaBuilder();

    final CriteriaQuery<Event> query = cb.createQuery(Event.class);

    final Root<Event> root = query.from(Event.class);


    final List<Predicate> predicates = new ArrayList<>();


    final List<Predicate> predicates = events.stream().map(event -> {

                return cb.and(cb.equal(root.get("name"), event.getName()),

                              cb.equal(root.get("location"), event.getLocation()),

                              cb.equal(root.get("date"), event.getDate()));

    }).collect(Collectors.toList());


    query.select(root).where(cb.or(predicates.toArray(new Predicate[]{})));


    return em.createQuery(query).getResultList();

}


查看完整回答
反对 回复 2021-09-03
?
皈依舞

TA贡献1851条经验 获得超3个赞

尝试

List<Event> findByNameInAndLocationInAndDateIn(List<String> names,List<String> locations,List<Date> dates);

但这将返回一个列表,而不是单个事件,如果您需要验证一个事件是否不在数据库中,唯一的方法是逐一搜索,您可以使用此函数来决定是否需要。

我不确定这个功能是否如你所愿


查看完整回答
反对 回复 2021-09-03
  • 2 回答
  • 0 关注
  • 307 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信