Spring Boot:查询方法中的可选参数查询

4

我刚开始接触Spring Boot和Hibernate。这里我试图运行一个基于可选参数查询的搜索,可以按名称、国家等进行搜索。如果我将此字段保持为空,则查询应返回全部列表。但问题在于,我的方法返回所有数据,忽略了我的搜索参数。我的模型类如下:

@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";
    }

有人能在这方面帮助我吗?拜托了。


你可以尝试使用规范(需要一些设置)https://spring.io/blog/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/ - Zeromus
4个回答

6

虽然现在已经太晚回答了,但对于任何仍在寻找解决方案的人来说,以下是更简单的方法:

在我的情况下,我的控制器如下所示:

@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,并且lengthoffset是必需的参数,但我接受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为null或o.id = :orderId)(:flag为null或o.flags = :flag)来检查我的可选参数,并且我认为需要强调的是我检查的是参数而不是我的列数据,所以如果客户端向我发送Idflags参数,我将使用它们来过滤结果,否则我将只查询我的@PathVariable——用户名username


4

我不知道为什么,但以下代码对我有效:

@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";
}

1

JPQL不支持可选参数。

在JPQL中没有简单的方法来实现此功能。您需要编写多个带有OR运算符的WHERE子句。

请参考类似问题的答案:答案 1答案 2

附注:对于您的用例,您可能需要查看示例查询。它支持处理空参数。


0

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

步骤1:在您的JPA Repository中实现JpaSpecificationExecutor

例如:

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

步骤2 现在,您可以使用CriteriaBuilder构建Specification查询来基于可选参数获取门票。

例如:

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]));
    };
}

第三步:将Specification实例传递给jpaRepo.findAll(specification),它将返回您的实体对象列表(在此运行示例中为Tickets)。
ticketRepo.findAll(specification); // Pass output of function in step 2 to findAll

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接