【问题标题】:Spring boot: Optional parameter query in Query methodSpring boot:Query方法中的可选参数查询
【发布时间】:2019-03-16 03:16:17
【问题描述】:

我是 Spring Boot 和休眠的新手。在这里,我正在尝试运行基于搜索的可选参数查询,我可以在其中按名称、国家/地区等进行搜索。如果我将此字段保持为空,则查询应全部列出。但问题是我的方法是返回所有数据而忽略了我的搜索参数。我的模型类看起来像

@Entity(name="MLFM_ORDER_OWNER")
public class ModelOrderOwner {

    @Id @GenericGenerator(name = "custom_sequence", strategy = 
            "com.biziitech.mlfm.IdGenerator")
    @GeneratedValue(generator = "custom_sequence")
    @Column(name="ORDER_OWNER_ID")
    private Long orderOwnerId;

    @Column(name="OWNER_NAME")
    private String ownerName;

    @OneToOne
    @JoinColumn(name="BUSINESS_TYPE_ID")
    private ModelBusinessType businessTypeId;

    @Column(name="SHORT_CODE")
    private String shortCode;


    @ManyToOne
    @JoinColumn(name="OWNER_COUNTRY")
    private ModelCountry ownerCountry;
// getter setter..

我的存储库界面看起来像

public interface OrderOwnerRepository extends 

    JpaRepository<ModelOrderOwner,Long>{
        @Query("select a from MLFM_ORDER_OWNER a where a.businessTypeId.typeId=coalsec(:typeId,a.businessTypeId.typeId) and a.ownerCountry.countryId=coalsec(:countryId,a.ownerCountry.countryId) and a.ownerName LIKE %:name and a.shortCode LIKE %:code")
        public List <ModelOrderOwner> findOwnerDetails(@Param("typeId")Long typeId,@Param("countryId")Long countryId,@Param("name")String name,@Param("code")String code);

    }

这是我在控制器中的方法

@RequestMapping(path="/owners/search")
     public String getAllOwner(Model model,@RequestParam("owner_name") String name,@RequestParam("shortCode") String code,

                            @RequestParam("phoneNumber") String phoneNumber,@RequestParam("countryName") Long countryId,
                            @RequestParam("businessType") Long typeId
             ) {
 model.addAttribute("ownerList",ownerRepository.findOwnerDetails(typeId, countryId, name, code));

            return "data_list";
    }

任何人都可以在这方面帮助我吗?请问?

【问题讨论】:

标签: java hibernate spring-boot jpql


【解决方案1】:

不知道如何,但下面的代码对我有用

@Query("select a from MLFM_ORDER_OWNER a  where a.businessTypeId.typeId=COALESCE(:typeId,a.businessTypeId.typeId) and a.ownerCountry.countryId=COALESCE(:countryId,a.ownerCountry.countryId) and a.ownerName LIKE %:name and a.shortCode LIKE %:code")
    public List <ModelOrderOwner> findOwnerDetails(@Param("typeId")Long typeId,@Param("countryId")Long countryId,@Param("name")String name,@Param("code")String code); 

在控制器中

@RequestMapping(path="/owners/search")
     public String getAllOwner(Model model,@RequestParam("owner_name") String name,@RequestParam("shortCode") String code,

                            @RequestParam("phoneNumber") String phoneNumber,@RequestParam("countryName") Long countryId,
                            @RequestParam(value = "active", required = false) String active, @RequestParam("businessType") Long typeId
             ) {




        if(typeId==0)
            typeId=null;
        if(countryId==0)
            countryId=null;

         model.addAttribute("ownerList",ownerRepository.findOwnerDetails(typeId, countryId, name, code, status));

            return "data_list";
    }

【讨论】:

    【解决方案2】:

    JPQL 不支持可选参数。 在 JPQL 中没有简单的方法可以做到这一点。您必须使用 OR 运算符编写多个 WHERE 子句。

    请参考以下类似问题的答案:Answer 1 & Answer 2

    PS:您可能需要查看Query by Example 以了解您的用例。支持对空参数的处理。

    【讨论】:

      【解决方案3】:

      使用JpaSpecificationExecutor //import org.springframework.data.jpa.repository.JpaSpecificationExecutor;

      第 1 步:在您的 JPA 存储库中实现 JpaSpecificationExecutor

      例如:

      public interface TicketRepo extends JpaRepository<Ticket, Long>, JpaSpecificationExecutor<Ticket> {
      

      第 2 步现在要根据可选参数获取票证,您可以使用 CriteriaBuilder 构建规范查询

      例如:

      public Specification<Ticket> getTicketQuery(Integer domainId, Calendar startDate, Calendar endDate, Integer gameId, Integer drawId) {
          return (root, query, criteriaBuilder) -> {
              List<Predicate> predicates = new ArrayList<>();
      
              predicates.add(criteriaBuilder.equal(root.get("domainId"), domainId));
              predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get("createdAt"), startDate));
              predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get("createdAt"), endDate));
      
              if (gameId != null) {
                  predicates.add(criteriaBuilder.equal(root.get("gameId"), gameId));
              }
      
              return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
          };
      }
      

      第 3 步:将 Specification 实例传递给 jpaRepo.findAll(specification),它将返回您的实体对象列表(在运行示例中为 Tickets)

      ticketRepo.findAll(specification); // Pass output of function in step 2 to findAll
      

      【讨论】:

        【解决方案4】:

        回答为时已晚,但是对于正在寻找解决方案的任何人来说,有一个更简单的方法如下:

        就我而言,我的控制器是这样的:

        @RestController
        @RequestMapping("/order")
        public class OrderController {
        
            private final IOrderService service;
        
            public OrderController(IOrderService service) {
                this.service = service;
            }
        
            @RequestMapping(value = "/{username}/", method = RequestMethod.GET)
            public ResponseEntity<ListResponse<UserOrdersResponse>> getUserOrders(
                    @RequestHeader Map<String, String> requestHeaders,
                    @RequestParam(required=false) Long id,
                    @RequestParam(required=false) Long flags,
                    @RequestParam(required=true) Long offset,
                    @RequestParam(required=true) Long length) {
                // Return successful response
                return new ResponseEntity<>(service.getUserOrders(requestDTO), HttpStatus.OK);
            }
        }
        

        如您所见,我有 Username@PathVariablelengthoffset 这是我的必需参数,但我接受 idflags 用于过滤搜索结果,所以它们是我的可选参数,对于调用 REST 服务不是必需的。

        现在在我的存储库层中,我刚刚创建了我的@Query,如下所示:

        @Query("select new com.ada.bourse.wealth.services.models.response.UserOrdersResponse(FIELDS ARE DELETED TO BECOME MORE READABLE)" +
                " from User u join Orders o on u.id = o.user.id where u.userName = :username" +
                " and (:orderId is null or o.id = :orderId) and (:flag is null or o.flags = :flag)")
        Page<UserOrdersResponse> findUsersOrders(String username, Long orderId, Long flag, Pageable page);
        

        就是这样,你可以看到我用(:orderId is null or o.id = :orderId)(:flag is null or o.flags = :flag)检查了我的可选参数,我认为需要强调的是我用is null检查了我的参数条件不是我的列数据,所以如果客户端为我发送Idflags 参数,我将用它们过滤结果,否则我只需使用username 查询,这是我的@PathVariable

        【讨论】:

          猜你喜欢
          • 2015-12-20
          • 1970-01-01
          • 2012-07-21
          • 2014-11-04
          • 2018-08-16
          • 2019-09-29
          • 2019-04-22
          • 1970-01-01
          相关资源
          最近更新 更多