Spring Data JPA 复杂查询方式总结
Spring Data JPA 是 Spring 借鉴了 Hibernate 实现的一套 JPA 规范实现。Spring Data JPA 使得我们在使用 JPA 进行数据库操作时能够更加简单方便。
下面我们来讲解 Spring Data JPA 如何进行复杂查询,包括多表关联查询和自定义分页查询。
多表关联查询
多表关联查询时,我们需要使用 JPA 中的关联注解,例如 @OneToOne、@OneToMany、@ManyToOne、@ManyToMany。
以订单和订单明细为例,订单和订单明细是多对多的关系。我们可以这样查询某个订单的所有订单明细:
public interface OrderRepository extends JpaRepository<Order, Integer>, JpaSpecificationExecutor<Order> {
@Query("select o from Order o left join fetch o.orderItems oi where o.id = ?1")
Optional<Order> findWithOrderItemsById(Integer id);
}
上面的代码中使用了 @Query 注解,可以在注解中书写 JPQL 语句。通过 left join fetch 关键字,我们可以同时查询出订单和订单明细,这样在后续的处理中可以减少对数据库的访问次数。
自定义分页查询
Spring Data JPA 默认提供了 Page 和 Pageable 接口,可以非常方便地实现分页查询。但是在某些场景下,我们需要自定义分页查询的条件和排序方式。
以商品为例,我们可以这样实现根据商品名字模糊查询的自定义分页查询:
public interface ProductRepository extends JpaRepository<Product, Integer>, JpaSpecificationExecutor<Product> {
default Page<Product> findByKeyword(String keyword, Pageable pageable) {
Specification<Product> spec = (root, query, criteriaBuilder) -> {
Predicate p1 = criteriaBuilder.like(root.get("name"), "%" + keyword + "%");
Predicate p2 = criteriaBuilder.like(root.get("description"), "%" + keyword + "%");
return criteriaBuilder.or(p1, p2);
};
return findAll(spec, pageable);
}
}
上面的代码中,我们通过实现 Pageable 接口的 findByKeyword 方法来实现自定义分页查询。在方法中,我们使用 JPA 中的 Specification 对象来封装查询条件。在 Specification 对象中,我们通过 CriteriaBuilder 对象来创建查询条件,例如 like 和 or。
最终,我们可以通过调用 findAll 方法并传递 Specification 和 Pageable 参数来实现分页查询。
示例
下面是一个完整的示例,包括多表关联查询和自定义分页查询:
@RestController
@RequestMapping("/orders")
public class OrderController {
@Autowired
private OrderRepository orderRepository;
@GetMapping("/{id}")
public Order findOrderById(@PathVariable Integer id) {
Optional<Order> optionalOrder = orderRepository.findWithOrderItemsById(id);
return optionalOrder.orElse(null);
}
@GetMapping("/")
public Page<Order> findOrdersByKeyword(@RequestParam String keyword,
@RequestParam(defaultValue = "0") Integer page,
@RequestParam(defaultValue = "10") Integer size) {
Pageable pageable = PageRequest.of(page, size);
return orderRepository.findByKeyword(keyword, pageable);
}
}
通过 GET 请求 /orders/{id} 可以查询某个订单的所有订单明细,通过 GET 请求 /orders/?keyword=xxx 可以根据订单名字模糊查询并分页返回结果。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring Data Jpa 复杂查询方式总结(多表关联及自定义分页) - Python技术站