弹簧数据 JPA。在中查找

Posted

技术标签:

【中文标题】弹簧数据 JPA。在中查找【英文标题】:Spring data JPA. Find by in 【发布时间】:2017-11-07 07:02:54 【问题描述】:

我的 spring 项目中有一个常用的 Spring Data JPA 存储库。

@Repository
public interface EventRepository extends CrudRepository<Event, Long> 
  List<Event> findByOriginalIdIn(Collection<String> originalEventIds);
  ...

我之前使用过findByOriginalIdIn 方法,效果很好。但是情况发生了变化,我需要使用对集合来处理相同的请求以查找和过滤正确的事件。

我的替代方法应该处理下一个逻辑: find by (originalId1 AND originalCalendarId1) OR (originalId2 AND originalCalendarId2) OR (originalId..N AND originalCalendarId..N) OR

是否可以使用Selectively exposing CRUD methods 处理此请求?如果是的话,我可以举个例子吗?

【问题讨论】:

你试过findByOriginalIdInOrOriginalIdInOrOriginalIdIn(...) ??但老实说,我认为 crietria api 使用起来会更简单直接 查看this问题 【参考方案1】:

为了不创建自定义存储库,我建议使用 Spring Data JPA 规范。 这是一个草稿示例。

       class Specification1 implements Specification<Event>             
            private final List<Pair<String, String>> pairs;

            public Specification1(List<Pair<String, String>> pairs) 
                this.paris = pairs;
            

            @Override
            public Predicate toPredicate(Root<Event> root, CriteriaQuery<?> query, CriteriaBuilder cb) 


                Predicate[] as = pairs.stream().map(pair -> 
                    return cb.and(cb.equal(root.get("originalId2"), pair.getKey())),cb.equal(root.get("originalCalendarId2"), pair.getKey());
                ).toArray(Predicate[]::new);

                return cb.or(as);
            
        


        userRepository.findAll(new Specification1(...));

此外,您的存储库必须扩展 JpaSpecificationExecutor。

【讨论】:

【参考方案2】:

尝试使用具有以下限制的条件:

Criteria criteria = session.createCriteria(Event.class)
                    .add(Restrictions.in("id", values));

【讨论】:

【参考方案3】:

我建议将 QueryDSL 与 Spring JPA 一起使用,以简化您的实现。

使用 QueryDSL,您可以轻松地构造谓词(除了条件)并在查询中使用它。在你的情况下,它可能会像下面这样。请参考链接:Spring Data JPA Tutorial: Creating Database Queries With Querydsl,了解如何将 QueryDSL 与 Spring Data JPA 结合使用。

在你的情况下,对于给定的条件,

find by (originalId1 AND originalCalendarId1) OR (originalId2 AND originalCalendarId2) OR (originalId..N AND originalCalendarId..N) OR

我不明白,例如originalId1/originalCalendarId1 应该等于任何值。假设,为了简单和解释,它们应该等于某个值。

import com.mysema.query.BooleanBuilder;
import com.mysema.query.types.Predicate;

public class EventPredicates 

    public static Predicate getAllEventsByOrginalIds(String[] originalIds, String[] originalCalendarIds) 
        QEvent event = QEventEntity.event;

        BooleanBuilder builder = new BooleanBuilder();

        //assuming both arrays are of same size.
        for (int idx = 0; idx < originalIds.length; idx++) 
            builder.or(event.originalIds[0].eq.(someValue)).and(event.originalCalendarIds[0].eq.(someCalValue));
        
        return builder;
    

但是,您的存储库接口应该扩展 QueryDslPredicateExecutor&lt;Event&gt; 以使用 QueryDSL 功能。

在您的服务方法中,假设 EventRepository 声明如下,您可以进行如下调用:

@Autowired
EventRepository eventRepository;

public void someMethod()

    ...
    List<Events> events = eventRepository.findAll(EventPredicates.getAllEventsByOrginalIds(originalIdsArr, originalCalendarIdsArr));
    ...


顺便说一句,QueryDSL 可以很容易地实现不同的标准(从简单到复杂)。使用方法请参考以上链接。

希望这会有所帮助。

【讨论】:

以上是关于弹簧数据 JPA。在中查找的主要内容,如果未能解决你的问题,请参考以下文章

弹簧状态机数据 jpa 示例问题

检查其他两个日期之间的日期弹簧数据jpa

弹簧数据 jpa。返回 Map 作为分组操作的结果

弹簧数据 JPA。子实体的分页

从控制器的结果集中排除列 |弹簧数据 jpa

带有谓词的弹簧数据 JPA 方法 findAll() - QueryDslPredicateExecutor