SpringData Jpa(二):五种不同查询方式

五种查询方式

父接口方法查询

  • 不用改变dao层
@SpringBootTest
@RunWith(SpringRunner.class)
public class Query1Test {

    @Autowired
    private ArticleDao articleDao;

    /**
     * 根据主键查询
     */
    @Test
    public void testFindById() {
        //根据一个主键查询
        Optional<Article> optional = articleDao.findById(21);
        System.out.println(optional.get());

        //根据多个主键查询
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(3);
        list.add(5);
        List<Article> articles = articleDao.findAllById(list);
        for (Article article : articles) {
            System.out.println(article);
        }
    }


    /**
     * 查询所有
     */
    @Test
    public void testFindAll() {
        List<Article> articles = articleDao.findAll();
        for (Article article : articles) {
            System.out.println(article);
        }
    }

    /**
     * 查询所有--排序
     */
    @Test
    public void testFindAllWithSort() {
        //按照aid倒序排列
        Sort sort = Sort.by(Sort.Order.desc("aid"));
        List<Article> articles = articleDao.findAll(sort);
        for (Article article : articles) {
            System.out.println(article);
        }
    }


    /**
     * 查询所有--分页
     */
    @Test
    public void testFindAllWithPage() {
        //处理分页条件
        //page   当前是第几页(从0开始)    size  每页大小
        Pageable pageable = PageRequest.of(0, 2);
        Page<Article> page = articleDao.findAll(pageable);

        //总记录数  总页数  每页多少
        System.out.println("总记录数:" + page.getTotalElements());
        System.out.println("总页数:" + page.getTotalPages());
        System.out.println("每页多少:" + page.getSize());
        
        //当前页的元素
        List<Article> content = page.getContent();
        for (Article article : content) {
            System.out.println(article);
        }
    }


    /**
     * 查询所有--分页+排序
     */
    @Test
    public void testFindAllWithPageAndPage() {
        //按照aid倒序排列
        Sort sort = Sort.by(Sort.Order.desc("aid"));

        //处理分页条件
        //page   当前是第几页(从0开始)    size  每页大小
        Pageable pageable = PageRequest.of(0, 2, sort);
        Page<Article> page = articleDao.findAll(pageable);

        //总记录数  总页数  每页多少
        System.out.println("总记录数:" + page.getTotalElements());
        System.out.println("总页数:" + page.getTotalPages());
        System.out.println("每页多少:" + page.getSize());
        
        //当前页的元素
        List<Article> content = page.getContent();
        for (Article article : content) {
            System.out.println(article);
        }
    }

}

方法命名规则查询

  • 需要在dao接口写方法(idea会有自动提示)
public interface ArticleDao extends JpaRepository<Article, Integer>, JpaSpecificationExecutor<Article> {

    //根据标题查询
    List<Article> findByTitle(String title);

    //根据标题模糊查询
    List<Article> findByTitleLike(String title);

    //根据标题和作者查询
    List<Article> findByTitleAndAuthor(String title, String author);

    //根据ID范围查询 > < between in
    List<Article> findByAidIsLessThan(Integer aid);

    List<Article> findByAidBetween(Integer startAid, Integer endAid);

    List<Article> findByAidIn(List<Integer> aids);

    //根据创建时间之后查询
    List<Article> findByCreateTimeAfter(Date createTime);
}

原理

  • SpringData JPA在程序执行的时候会根据方法名称进行解析,并自动生成查询语句进行查询.
  • 按照SpringData JPA定义的规则:
    • 查询方法以findBy开头,涉及条件查询时,条件的属性用条件关键 字连接,要注意的是:条件属性首字母需大写。
    • 框架在进行方法名解析时,会先把方法名多余的前缀截取掉, 然后对剩下部分进行解析。
关键字 例子 对应的JPQL语句
And findByLastnameAndFirstname … where x.lastname = ?1 and x.firstname = ? 2
Or findByLastnameOrFirstname … where x.lastname = ?1 or x.firstname = ?2
Is,Equals findByFirstnameIs,findByFirstnameEquals … where x.firstname = ?1
Between findByStartDateBetween … where x.startDate between ?1 and ?2
LessThan findByAgeLessThan … where x.age < ?1
LessThanEqual findByAgeLessThanEqual … where x.age ⇐ ?1
GreaterThan findByAgeGreaterThan … where x.age > ?1
GreaterThanEqual findByAgeGreaterThanEqual … where x.age >= ?1
After findByStartDateAfter … where x.startDate > ?1
Before findByStartDateBefore … where x.startDate < ?1
IsNull findByAgeIsNull … where x.age is null
IsNotNull,NotNull findByAge(Is)NotNull … where x.age not null
Like findByFirstnameLike … where x.firstname like ?1
NotLike findByFirstnameNotLike … where x.firstname not like ?1
StartingWith findByFirstnameStartingWith … where x.firstname like ?1 (parameter bound withappended %)
EndingWith findByFirstnameEndingWith … where x.firstname like ?1 (parameter bound with prepended %)
Containing findByFirstnameContaining … where x.firstname like ?1 (parameter bound wrapped in%)
OrderBy findByAgeOrderByLastnameDesc … where x.age = ?1 order by x.lastname desc
Not findByLastnameNot … where x.lastname <> ?1
In findByAgeIn(Collection ages) … … where x.age in ?1
NotIn findByAgeNotIn(Collection age) … where x.age not in ?1
TRUE findByActiveTrue() … where x.active = true
FALSE findByActiveFalse() … where x.active = false
IgnoreCase findByFirstnameIgnoreCase … where UPPER(x.firstame) = U

JPQL查询

  • 使用SpringData JPA提供的查询方法已经可以解决大部分的应用场景,但是对于某些业务来说,我们还需要灵活的构造查询条件,这时就可以使用@Query注解,结合JPQL的语句方式完成查询。
  • JPQL,全称是Java Persistence Query Language。JPQL语句是JPA中定义的一种查询语言,此种语言的用意是让开发者忽略数据库表和表中的字段,而关注实体类及实体类中的属性。它的写法十分类似于SQL语句的写法,但是要把查询的表名换成实体类名称,把表中的字段名换成实体类的属性名称
  • 需要在dao接口写方法及JPQL查询语句
public interface ArticleDao extends JpaRepository<Article, Integer>, JpaSpecificationExecutor<Article> {

   //JPQL:类似于SQL语句,但是要使用实体类名代替表名,使用属性名代替字段名[面向对象查询]
    //展示位置参数绑定[按照title和author查询]
    //占位符从1开始
    @Query("from Article a where a.title = ?1 and a.author =?2")
    List<Article> findByCondition1(String title, String author);

    //展示名字参数绑定
    @Query("from Article a where a.title = :title and a.author = :authors")
    List<Article> findByCondition2(@Param("title") String title, @Param("authors") String author);

    //展示like模糊查询
    @Query("from Article a where a.title like %:title%")
    List<Article> findByCondition3(@Param("title") String title);

    //展示排序查询
    @Query("from Article a where a.title like %:title% order by a.aid desc ")
    List<Article> findByCondition4(@Param("title") String title);

    //展示分页查询
    @Query("from Article a where a.title like %:title%")
    List<Article> findByCondition5(Pageable pageable, @Param("title") String title);

    //展示传入集合参数查询
    @Query("from Article a where a.aid in :aids")
    List<Article> findByCondition6(@Param("aids") List<Integer> aids);

    //展示传入Bean进行查询(SPEL表达式查询)
    @Query("from Article a where a.title = :#{#article.title} and a.author = :#{#article.author}")
    List<Article> findByCondition7(@Param("article") Article article);

}

注意:

  • JPQL类似于SQL语句,但注意
    • 使用:实体类名 代替 表名
    • 使用:实体类.属性名 代替 字段名
  • 获取参数的方式
    • ?下标:不推荐
    • :参数名:推荐使用(参数必须使用@Param()注解)
    • :#{# }:解析对象的属性(参数必须使用@Param()注解)

本地SQL查询

  • 基本不会使用,除非是出现非常复杂的业务情况导致SQL非常复杂,JPQL搞不定的时候
  • 需要在dao接口写方法及普通的SQL查询语句
public interface ArticleDao extends JpaRepository<Article, Integer>, JpaSpecificationExecutor<Article> {

    //本地SQL查询 将nativeQuery改为true
    @Query(value = "select * from article a where a.title = ?1 and a.author =?2", nativeQuery = true)
    List<Article> findByCondition8(String title, String author);
    
}

Specifications动态查询

  • 有时我们在查询某个实体的时候,给定的条件是不固定的,这时就需要动态构建相应的查询语句
  • 在 Spring Data JPA 中可以通过 JpaSpecificationExecutor 接口查询。相比 JPQL,其优势是类型安全,更加的面向对象,缺点是书写比较麻烦。
  • 不用改变dao层接口
@SpringBootTest
@RunWith(SpringRunner.class)
public class JpaSpecificationTest {

    @Autowired
    private ArticleDao articleDao;


    /**
     * 按照标题和作者进行查询,以不为空的属性作为查询条件
     */
    @Test
    public void testFindAll() {

        //就模拟从从外边传入的变量
        String title = "a_3";
        String author = "";

        List<Article> articles = articleDao.findAll(new Specification<Article>() {

            /**
             * @param root  代表实体对象,可以通过它的get方法 获取到该字段 然后给该字段设置条件
             * @param cq    用于生成SQL语句
             * @param cb    用于拼接查询条件
             * @return
             */
            @Override
            public Predicate toPredicate(Root<Article> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {

                List<Predicate> list = new ArrayList<>();
                if (!StringUtils.isEmpty(title)) {
                    //拼接作为查询条件
                    Predicate predicate = cb.equal(root.get("title").as(String.class), title);
                    list.add(predicate);
                }
                if (!StringUtils.isEmpty(author)) {
                    //拼接作为查询条件
                    Predicate predicate = cb.equal(root.get("author").as(String.class), author);
                    list.add(predicate);
                }
				
				//组合上面的所有查询条件
                return cb.and(list.toArray(new Predicate[]{}));
            }
        });

        for (Article article : articles) {
            System.out.println(article);
        }
    }


	/**
	 * 测试动态sql+分页查询
	 */
    @Test
    public void testFindAllWithPage() {

        //就模拟从从外边传入的变量
        String title = "";
        String author = "";

        //分页
        Pageable pageable = PageRequest.of(0, 3);

        Page<Article> page = articleDao.findAll(new Specification<Article>() {
        
            @Override
            public Predicate toPredicate(Root<Article> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {

                List<Predicate> list = new ArrayList<>();
                if (!StringUtils.isEmpty(title)) {
                    //拼接作为查询条件
                    Predicate predicate = cb.equal(root.get("title").as(String.class), title);
                    list.add(predicate);
                }
                if (!StringUtils.isEmpty(author)) {
                    //拼接作为查询条件
                    Predicate predicate = cb.equal(root.get("author").as(String.class), author);
                    list.add(predicate);
                }

                return cb.and(list.toArray(new Predicate[]{}));
            }
        }, pageable);

        for (Article article : page.getContent()) {
            System.out.println(article);
        }
    }

	/**
	 * 测试动态sql+分页查询+排序
	 */
    @Test
    public void testFindAllWithPageAndSort() {

        //就模拟从从外边传入的变量
        String title = "";
        String author = "";

        //分页 加一个参数Sort
        Pageable pageable = PageRequest.of(0, 3, Sort.by(Sort.Order.desc("aid")));

        Page<Article> page = articleDao.findAll(new Specification<Article>() {
        
            @Override
            public Predicate toPredicate(Root<Article> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {

                List<Predicate> list = new ArrayList<>();
                if (!StringUtils.isEmpty(title)) {
                    //拼接作为查询条件
                    Predicate predicate = cb.equal(root.get("title").as(String.class), title);
                    list.add(predicate);
                }
                if (!StringUtils.isEmpty(author)) {
                    //拼接作为查询条件
                    Predicate predicate = cb.equal(root.get("author").as(String.class), author);
                    list.add(predicate);
                }

                return cb.and(list.toArray(new Predicate[]{}));
            }
        }, pageable);

        for (Article article : page.getContent()) {
            System.out.println(article);
        }
    }


}
发布了109 篇原创文章 · 获赞 47 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/weixin_43934607/article/details/103248529
今日推荐