JPA查询的几种形式

  1. 基础形式
    此种方法不用写sql,继承JpaRepository,适合简单的增删改查。
    例子:一般针对简单的查询:

    1
    2
    3
    4
    5
    @Repository
    public interface ProductAttributeValueRepository extends JpaRepository<ProductAttributeValue,Long> {
    int deleteAllByCateId(Long id);
    int deleteAllByAttrNameId(Long id);
    }
  2. SQL,JPQL查询
    sql查询为原生SQL查询,JPQL查询是使用的是基于对象的查询。
    Modifying:它说的是可以清除底层持久化上下文,就是entityManager这个类,我们知道jpa底层实现会有二级缓存,也就是在更新完数据库后,如果后面去用这个对象,你再去查这个对象,这个对象是在一级缓存,但是并没有跟数据库同步,这个时候用clearAutomatically=true,就会刷新hibernate的一级缓存了

    1
    2
    3
    4
    5
    6
    @Repository
    public interface ProductCategoryRepository extends JpaRepository<ProductCategoryEntity, Long> {
    @Modifying(clearAutomatically = true)
    @Query(value = "update product_category pc set pc.`is_delete`=1 where pc.`cate_id`=?1", nativeQuery = true)
    int deleteCategoryById(long id);
    }
  3. 组装形式的原生SQL
    这种形式,适合查询条件比较复杂的情况,自己组装比较灵活

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
       
    public ProductInfoDto searchProductInfoWithTitle(Long productInfoId){
    String sql = "select pi.*,pb.title as brand_title,pc.title as category_title from product_info pi " +
    "left join product_brand pb on pi.brand_id=pb.brand_id " +
    "left join product_category pc on pc.cate_id=pi.cate_id " +
    "where pi.id=" + productInfoId + " and pi.is_delete=0 ";
    List<ProductInfoDto> webInfos = entityManager.createNativeQuery(sql, ProductInfoDto.class).getResultList();
    if (webInfos == null || webInfos.size() == 0) {
    return null;
    }
    ProductInfoDto productInfoDto = webInfos.get(0);
    return productInfoDto;
    }
  4. Querydsl方式

    1
    2
    interface UserRepository extends CrudRepository<User, Long>, QuerydslPredicateExecutor<User> {
    }

    使用方法:

    1
    2
    3
    4
    Predicate predicate = user.firstname.equalsIgnoreCase("dave")
    .and(user.lastname.startsWithIgnoreCase("mathews"));

    userRepository.findAll(predicate);
  5. 使用Example
    我一开始特别喜欢这种形式的查询,比较直观,ExampleMatcher是一个查询的匹配器,可以设置多种匹配规则,分页也比较直观

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13

    Sort sort = new Sort(Sort.Direction.DESC, "brandId");
    Pageable pageable = PaginationUtil.pageRequest(productBrandListDtoIn, sort);
    ExampleMatcher exampleMatcher = ExampleMatcher.matching().withMatcher("title", ExampleMatcher.GenericPropertyMatchers.contains());
    Example<ProductBrand> example = Example.of(productBrandListDtoIn.getProductBrand(), exampleMatcher);
    Page<ProductBrand> productBrandPage =productBrandRepository.findAll(example, pageable);
    ProductBrandListDtoOut dtoOut = new ProductBrandListDtoOut(productBrandPage);
    if (productBrandPage.getContent().size() > 0) {
    productBrandPage.getContent().forEach(entity ->
    dtoOut.getList().add(dtoOut.convertToDto(entity))
    );
    }
    return dtoOut;
  1. nameQuery方法
    1
    2
    3
    4
    5
    6
    @Entity
    @NamedQuery(name = "User.findByEmailAddress",
    query = "select u from User u where u.emailAddress = ?1")
    public class User {

    }