【问题标题】:Spring data JPA. Find by in弹簧数据 JPA。在中查找
【发布时间】: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问题

标签: java spring spring-data spring-data-jpa jpql


【解决方案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 可以很容易地实现不同的标准(从简单到复杂)。使用方法请参考以上链接。

      希望这会有所帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-01-03
        • 2017-07-06
        • 1970-01-01
        • 2016-06-02
        • 2012-08-03
        • 2016-07-09
        相关资源
        最近更新 更多