美文网首页JAVA随笔码农日历
SpringBoot系列教程JPA之query使用姿势详解之基础

SpringBoot系列教程JPA之query使用姿势详解之基础

作者: 一灰灰blog | 来源:发表于2019-08-22 21:51 被阅读0次

    前面的几篇文章分别介绍了CURD中的增删改,接下来进入最最常见的查询篇,看一下使用jpa进行db的记录查询时,可以怎么玩

    本篇将介绍一些基础的查询使用姿势,主要包括根据字段查询,and/or/in/like/between 语句,数字比较,排序以及分页

    I. 环境准备

    在开始之前,当然得先准备好基础环境,如安装测试使用mysql,创建SpringBoot项目工程,设置好配置信息等,关于搭建项目的详情可以参考前一篇文章

    下面简单的看一下演示添加记录的过程中,需要的配置

    1. 表准备

    沿用前一篇的表,结构如下

    CREATE TABLE `money` (
      `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
      `name` varchar(20) NOT NULL DEFAULT '' COMMENT '用户名',
      `money` int(26) NOT NULL DEFAULT '0' COMMENT '钱',
      `is_deleted` tinyint(1) NOT NULL DEFAULT '0',
      `create_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
      `update_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
      PRIMARY KEY (`id`),
      KEY `name` (`name`)
    ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
    

    2. 项目配置

    配置信息,与之前有一点点区别,我们新增了更详细的日志打印;本篇主要目标集中在添加记录的使用姿势,对于配置说明,后面单独进行说明

    ## DataSource
    spring.datasource.url=jdbc:mysql://127.0.0.1:3306/story?useUnicode=true&characterEncoding=UTF-8&useSSL=false
    spring.datasource.driver-class-name=com.mysql.jdbc.Driver
    spring.datasource.username=root
    spring.datasource.password=
    ## jpa相关配置
    spring.jpa.database=MYSQL
    spring.jpa.hibernate.ddl-auto=none
    spring.jpa.show-sql=true
    spring.jackson.serialization.indent_output=true
    spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
    

    3. 数据准备

    数据修改嘛,所以我们先向表里面插入两条数据,用于后面的操作

    INSERT INTO `money` (`id`, `name`, `money`, `is_deleted`, `create_at`, `update_at`)
    VALUES
        (1, '一灰灰blog', 100, 0, '2019-04-18 17:01:40', '2019-04-18 17:01:40'),
        (2, '一灰灰2', 200, 0, '2019-04-18 17:01:40', '2019-04-18 17:01:40'),
        (3, '一灰灰3', 300, 0, '2019-04-18 17:01:40', '2019-04-18 17:01:40'),
        (4, '一灰灰4', 400, 0, '2019-04-18 17:01:40', '2019-04-18 17:01:40'),
        (5, '一灰灰5', 500, 0, '2019-04-18 17:01:40', '2019-04-18 17:01:40'),
        (6, 'Batch 一灰灰blog', 100, 0, '2019-04-18 17:01:40', '2019-04-18 17:01:40'),
        (7, 'Batch 一灰灰blog 2', 100, 0, '2019-04-18 17:01:40', '2019-04-18 17:01:40'),
        (8, 'Batch 一灰灰 3', 200, 0, '2019-04-18 17:01:40', '2019-04-18 17:01:40'),
        (9, 'Batch 一灰灰 4', 200, 0, '2019-04-18 17:01:40', '2019-04-18 17:01:40'),
        (10, 'batch 一灰灰5', 1498, 0, '2019-04-18 17:01:40', '2019-04-18 17:01:58'),
        (11, 'batch 一灰灰6', 1498, 0, '2019-04-18 17:01:40', '2019-04-18 17:01:58'),
        (12, 'batch 一灰灰7', 400, 0, '2019-04-18 17:01:40', '2019-04-18 17:01:40'),
        (13, 'batch 一灰灰8', 400, 0, '2019-04-18 17:01:40', '2019-04-18 17:01:40');
    
    db

    II. Query基本使用姿势

    下面进入简单的查询操作姿势介绍,单表的简单and/or/in/compare查询方式

    1. 表关联POJO

    查询返回的记录与一个实体类POJO进行绑定,借助前面的分析结果,如下

    @Data
    @DynamicUpdate
    @DynamicInsert
    @Entity
    @Table(name = "money")
    public class MoneyPO {
        @Id
        // 如果是auto,则会报异常 Table 'mysql.hibernate_sequence' doesn't exist
        // @GeneratedValue(strategy = GenerationType.AUTO)
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "id")
        private Integer id;
    
        @Column(name = "name")
        private String name;
    
        @Column(name = "money")
        private Long money;
    
        @Column(name = "is_deleted")
        private Byte isDeleted;
    
        @Column(name = "create_at")
        @CreatedDate
        private Timestamp createAt;
    
        @Column(name = "update_at")
        @CreatedDate
        private Timestamp updateAt;
    
    }
    

    上面类中的几个注解,说明如下

    • @Data 属于lombok注解,与jpa无关,自动生成getter/setter/equals/hashcode/tostring等方法
    • @Entity, @Table jpa注解,表示这个类与db的表关联,具体匹配的是表 money
    • @Id @GeneratedValue 作用与自增主键
    • @Column表明这个属性与表中的某列对应
    • @CreateDate根据当前时间来生成默认的时间戳

    2. Repository API声明

    接下来我们新建一个api继承自CurdRepository,然后通过这个api来与数据库打交道,后面会在这个类中添加较多的查询方法

    public interface MoneyBaseQueryRepository extends CrudRepository<MoneyPO, Integer> {
    }
    

    3. 使用姿势

    a. 根据id查询

    CrudRepository已经提供的功能,根据主键id进行查询,对于使用者而言,没有什么需要额外操作的,直接访问即可

    private void queryById() {
        // 根据主键查询,直接使用接口即可
        Optional<MoneyPO> res = moneyCurdRepository.findById(1);
        System.out.println("queryById return: " + res.get());
    }
    

    b. 根据字段查询

    除了根据主键查询,实际的业务场景中,根据某个字段进行查询的case,简直不要更多,在jpa中可以怎么做呢?

    • Repository接口中声明一个方法,命名规则为
    • findByXXX 或者 queryByXXX (注意这里的xxx用POJO中的成员名替换,表示根据这个成员进行查询)

    一个简单的case,如果我希望实现根据name进行查询,那么在MoneyBaseQueryRepository中添加下面两个方法中的任意一个都可以

    /**
     * 根据用户名查询
     *
     * @param name
     * @return
     */
    List<MoneyPO> findByName(String name);
    
    List<MoneyPO> queryByName(String name);
    

    如果需要多个成员的查询呢?也简单,形如findByXxxAndYyyy相当于sql中的where xxxx=? and yyy=?

    如我们也可以增加下面两个方法(一个and、一个or查询)

    /**
     * 根据用户名 + money查询
     *
     * @param name
     * @param money
     * @return
     */
    List<MoneyPO> findByNameAndMoney(String name, Long money);
    
    
    /**
     * 根据用户名 or id查询
     *
     * @param name
     * @param id
     * @return
     */
    List<MoneyPO> findByNameOrId(String name, Integer id);
    

    一个简单的测试case可以如下

    private void queryByField() {
        // 根据内部成员进行查询,需要自己定义新的接口
        String name = "一灰灰blog";
        Iterable<MoneyPO> res = moneyCurdRepository.findByName(name);
        System.out.println("findByName return: " + res);
    
        res = moneyCurdRepository.queryByName(name);
        System.out.println("queryByName return: " + res);
    
        Long money = 100L;
        res = moneyCurdRepository.findByNameAndMoney(name, money);
        System.out.println("findByNameAndMoney return: " + res);
    
        Integer id = 5;
        res = moneyCurdRepository.findByNameOrId(name, id);
        System.out.println("findByNameOrId return: " + res);
    }
    

    执行之后输出结果如下,下面也包括了对应的sql,便于理解

    Hibernate: select moneypo0_.id as id1_0_, moneypo0_.create_at as create_a2_0_, moneypo0_.is_deleted as is_delet3_0_, moneypo0_.money as money4_0_, moneypo0_.name as name5_0_, moneypo0_.update_at as update_a6_0_ from money moneypo0_ where moneypo0_.name=?
    findByName return: [MoneyPO(id=1, name=一灰灰blog, money=100, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0)]
    -------- 人工拆分 -----------
    Hibernate: select moneypo0_.id as id1_0_, moneypo0_.create_at as create_a2_0_, moneypo0_.is_deleted as is_delet3_0_, moneypo0_.money as money4_0_, moneypo0_.name as name5_0_, moneypo0_.update_at as update_a6_0_ from money moneypo0_ where moneypo0_.name=?
    queryByName return: [MoneyPO(id=1, name=一灰灰blog, money=100, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0)]
    -------- 人工拆分 -----------
    Hibernate: select moneypo0_.id as id1_0_, moneypo0_.create_at as create_a2_0_, moneypo0_.is_deleted as is_delet3_0_, moneypo0_.money as money4_0_, moneypo0_.name as name5_0_, moneypo0_.update_at as update_a6_0_ from money moneypo0_ where moneypo0_.name=? and moneypo0_.money=?
    findByNameAndMoney return: [MoneyPO(id=1, name=一灰灰blog, money=100, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0)]
    -------- 人工拆分 -----------
    Hibernate: select moneypo0_.id as id1_0_, moneypo0_.create_at as create_a2_0_, moneypo0_.is_deleted as is_delet3_0_, moneypo0_.money as money4_0_, moneypo0_.name as name5_0_, moneypo0_.update_at as update_a6_0_ from money moneypo0_ where moneypo0_.name=? or moneypo0_.id=?
    findByNameOrId return: [MoneyPO(id=1, name=一灰灰blog, money=100, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0), MoneyPO(id=5, name=一灰灰5, money=500, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0)]
    

    c. like查询

    上面的查询方式为等值查询,当在sql中除了等值查询(即=查询)之外,还有各种比较查询,不等查询以及like语句,在jpa中也比较简单,在repository定义的方法名,加一个like即可

    /**
     * like查询
     *
     * @param name
     * @return
     */
    List<MoneyPO> findByNameLike(String name);
    

    使用的时候,需要稍微注意一下,根据实际情况决定要不要加上 '%'

    private void queryByLike() {
        // like 语句查询
        String name = "一灰灰%";
        Iterable<MoneyPO> res = moneyCurdRepository.findByNameLike(name);
        System.out.println("findByName like: " + res);
    }
    

    输出结果为

    Hibernate: select moneypo0_.id as id1_0_, moneypo0_.create_at as create_a2_0_, moneypo0_.is_deleted as is_delet3_0_, moneypo0_.money as money4_0_, moneypo0_.name as name5_0_, moneypo0_.update_at as update_a6_0_ from money moneypo0_ where moneypo0_.name like ?
    findByName like: [MoneyPO(id=1, name=一灰灰blog, money=100, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0), MoneyPO(id=2, name=一灰灰2, money=200, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0), MoneyPO(id=3, name=一灰灰3, money=300, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0), MoneyPO(id=4, name=一灰灰4, money=400, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0), MoneyPO(id=5, name=一灰灰5, money=500, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0)]
    

    d. in查询

    对于in查询,CurdRepository提供了根据主键id的查询方式,直接调用findAllById即可,如果是其他的,可以通过声明一个接口的方式来支持

    /**
     * in查询
     *
     * @param moneys
     * @return
     */
    List<MoneyPO> findByMoneyIn(List<Long> moneys);
    

    测试case如下

    // in 查询
    List<Integer> ids = Arrays.asList(1, 2, 3);
    Iterable<MoneyPO> res = moneyCurdRepository.findAllById(ids);
    System.out.println("findByIds return: " + res);
    
    res = moneyCurdRepository.findByMoneyIn(Arrays.asList(400L, 300L));
    System.out.println("findByMoneyIn return: " + res);
    

    输出结果

    Hibernate: select moneypo0_.id as id1_0_, moneypo0_.create_at as create_a2_0_, moneypo0_.is_deleted as is_delet3_0_, moneypo0_.money as money4_0_, moneypo0_.name as name5_0_, moneypo0_.update_at as update_a6_0_ from money moneypo0_ where moneypo0_.id in (? , ? , ?)
    findByIds return: [MoneyPO(id=1, name=一灰灰blog, money=100, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0), MoneyPO(id=2, name=一灰灰2, money=200, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0), MoneyPO(id=3, name=一灰灰3, money=300, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0)]
    ------ 手动拆分 ----------
    Hibernate: select moneypo0_.id as id1_0_, moneypo0_.create_at as create_a2_0_, moneypo0_.is_deleted as is_delet3_0_, moneypo0_.money as money4_0_, moneypo0_.name as name5_0_, moneypo0_.update_at as update_a6_0_ from money moneypo0_ where moneypo0_.money in (? , ?)
    findByMoneyIn return: [MoneyPO(id=3, name=一灰灰3, money=300, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0), MoneyPO(id=4, name=一灰灰4, money=400, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0), MoneyPO(id=12, name=batch 一灰灰7, money=400, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0), MoneyPO(id=13, name=batch 一灰灰8, money=400, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0)]
    

    e. 比较查询

    数字的比较查询,比如大于等于,大于,小于,小于等于,between,下面的三个方法声明,应该能直观表示这种方式可以如何写

    /**
     * 查询大于or等于指定id的所有记录
     *
     * @param id
     * @return
     */
    List<MoneyPO> findByIdGreaterThanEqual(Integer id);
    
    /**
     * 查询小于or等于指定id的所有记录
     *
     * @param id
     * @return
     */
    List<MoneyPO> findByIdLessThanEqual(Integer id);
    
    /**
     * between查询
     *
     * @param low
     * @param high
     * @return
     */
    List<MoneyPO> findByIdIsBetween(Integer low, Integer high);
    

    下面是简单的映射关系

    • > : xxGreaterThan
    • >=: xxGreaterThanEqual
    • <: xxLessThan
    • <=: xxLessThanEqual
    • !=: xxNot
    • between a and b : xxIsBetween

    测试case如下

    private void queryByCompare() {
        Integer id1 = 3;
        Iterable<MoneyPO> res = moneyCurdRepository.findByIdLessThanEqual(id1);
        System.out.println("findByIdLessThan 3 return: " + res);
    
    
        Integer id2 = 10;
        res = moneyCurdRepository.findByIdGreaterThanEqual(id2);
        System.out.println("findByIdGreaterThan 10 return: " + res);
    
        id1 = 4;
        id2 = 6;
        res = moneyCurdRepository.findByIdIsBetween(id1, id2);
        System.out.println("findByIdsWBetween 3, 10 return: " + res);
    }
    

    输出结果为

    Hibernate: select moneypo0_.id as id1_0_, moneypo0_.create_at as create_a2_0_, moneypo0_.is_deleted as is_delet3_0_, moneypo0_.money as money4_0_, moneypo0_.name as name5_0_, moneypo0_.update_at as update_a6_0_ from money moneypo0_ where moneypo0_.id<=?
    findByIdLessThan 3 return: [MoneyPO(id=1, name=一灰灰blog, money=100, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0), MoneyPO(id=2, name=一灰灰2, money=200, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0), MoneyPO(id=3, name=一灰灰3, money=300, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0)]
    ------ 手动拆分 ----------
    Hibernate: select moneypo0_.id as id1_0_, moneypo0_.create_at as create_a2_0_, moneypo0_.is_deleted as is_delet3_0_, moneypo0_.money as money4_0_, moneypo0_.name as name5_0_, moneypo0_.update_at as update_a6_0_ from money moneypo0_ where moneypo0_.id>=?
    findByIdGreaterThan 10 return: [MoneyPO(id=10, name=batch 一灰灰5, money=1498, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:58.0), MoneyPO(id=11, name=batch 一灰灰6, money=1498, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:58.0), MoneyPO(id=12, name=batch 一灰灰7, money=400, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0), MoneyPO(id=13, name=batch 一灰灰8, money=400, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0)]
    ------ 手动拆分 ----------
    Hibernate: select moneypo0_.id as id1_0_, moneypo0_.create_at as create_a2_0_, moneypo0_.is_deleted as is_delet3_0_, moneypo0_.money as money4_0_, moneypo0_.name as name5_0_, moneypo0_.update_at as update_a6_0_ from money moneypo0_ where moneypo0_.id between ? and ?
    findByIdsWBetween 3, 10 return: [MoneyPO(id=4, name=一灰灰4, money=400, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0), MoneyPO(id=5, name=一灰灰5, money=500, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0), MoneyPO(id=6, name=Batch 一灰灰blog, money=100, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0)]
    

    f. 排序

    排序也属于基本查询的case了,jpa的实现中,通过加上OrderByXxxAsc/Desc的方式来决定根据什么进行升序or降序

    /**
     * 根据money查询,并将最终的结果根据id进行倒排
     *
     * @param money
     * @return
     */
    List<MoneyPO> findByMoneyOrderByIdDesc(Long money);
    
    /**
     * 根据多个条件进行排序
     *
     * @param id
     * @return
     */
    List<MoneyPO> queryByIdGreaterThanEqualOrderByMoneyDescIdAsc(Integer id);
    

    在根据多个列进行排序时,需要注意的是不能写多个 OrderBy 而是直接在OrderBy后面加上对应的xxxAscyyyDesc

    测试代码如

    private void queryWithSort() {
        // 排序
        Long money = 400L;
        Iterable<MoneyPO> res = moneyCurdRepository.findByMoneyOrderByIdDesc(money);
        System.out.println("findByMoneyAndOrderByIdDesc return: " + res);
      
        Integer startId = 7;
        res = moneyCurdRepository.queryByIdGreaterThanEqualOrderByMoneyDescIdAsc(startId);
        System.out.println("queryByIdGreaterThanEqualOrderByMoneyDescIdAsc return: " + res);
    }
    

    输出结果如下

    Hibernate: select moneypo0_.id as id1_0_, moneypo0_.create_at as create_a2_0_, moneypo0_.is_deleted as is_delet3_0_, moneypo0_.money as money4_0_, moneypo0_.name as name5_0_, moneypo0_.update_at as update_a6_0_ from money moneypo0_ where moneypo0_.money=? order by moneypo0_.id desc
    findByMoneyAndOrderByIdDesc return: [MoneyPO(id=13, name=batch 一灰灰8, money=400, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0), MoneyPO(id=12, name=batch 一灰灰7, money=400, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0), MoneyPO(id=4, name=一灰灰4, money=400, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0)]
    ------------- 人工拆分 --------
    Hibernate: select moneypo0_.id as id1_0_, moneypo0_.create_at as create_a2_0_, moneypo0_.is_deleted as is_delet3_0_, moneypo0_.money as money4_0_, moneypo0_.name as name5_0_, moneypo0_.update_at as update_a6_0_ from money moneypo0_ where moneypo0_.id>=? order by moneypo0_.money desc, moneypo0_.id asc
    queryByIdGreaterThanEqualOrderByMoneyDescIdAsc return: [MoneyPO(id=10, name=batch 一灰灰5, money=1498, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:58.0), MoneyPO(id=11, name=batch 一灰灰6, money=1498, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:58.0), MoneyPO(id=12, name=batch 一灰灰7, money=400, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0), MoneyPO(id=13, name=batch 一灰灰8, money=400, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0), MoneyPO(id=8, name=Batch 一灰灰 3, money=200, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0), MoneyPO(id=9, name=Batch 一灰灰 4, money=200, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0), MoneyPO(id=7, name=Batch 一灰灰blog 2, money=100, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0)]
    

    g. 分页查询

    分页有两种方式,一个是查询最大的多少条数据,一个是正常的limit/offset方式,下面是一个简单的实例demo

    /**
    * 分页查询,获取前面三个数据
    *
    * @param id
    * @return
    */
    List<MoneyPO> findTop3ByIdGreaterThan(Integer id);
    
    /**
    * 分页查询
    *
    * @param id
    * @param pageable page 从0开始表示查询第0页,即返回size个正好>id数量的数据
    * @return
    */
    List<MoneyPO> findByIdGreaterThan(Integer id, Pageable pageable);
    

    对于分页而言,通过传入参数Pageable来表明即可

    测试case如

    private void queryWithPageSize() {
        // 分页查询
        Iterable<MoneyPO> res = moneyCurdRepository.findTop3ByIdGreaterThan(3);
        System.out.println("findTop3ByIdGreaterThan 3 return: " + res);
    
        // id>3,第2页,每页3条,如果id递增时,则返回的第一条id=4 + 2 * 3 = 10
        res = moneyCurdRepository.findByIdGreaterThan(3, PageRequest.of(2, 3));
        System.out.println("findByIdGreaterThan 3 pageIndex 2 size 3 return: " + res);
    }
    

    输出结果为

    Hibernate: select moneypo0_.id as id1_0_, moneypo0_.create_at as create_a2_0_, moneypo0_.is_deleted as is_delet3_0_, moneypo0_.money as money4_0_, moneypo0_.name as name5_0_, moneypo0_.update_at as update_a6_0_ from money moneypo0_ where moneypo0_.id>? limit ?
    findTop3ByIdGreaterThan 3 return: [MoneyPO(id=4, name=一灰灰4, money=400, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0), MoneyPO(id=5, name=一灰灰5, money=500, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0), MoneyPO(id=6, name=Batch 一灰灰blog, money=100, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0)]
    ---------- 人工拆分 ------------
    Hibernate: select moneypo0_.id as id1_0_, moneypo0_.create_at as create_a2_0_, moneypo0_.is_deleted as is_delet3_0_, moneypo0_.money as money4_0_, moneypo0_.name as name5_0_, moneypo0_.update_at as update_a6_0_ from money moneypo0_ where moneypo0_.id>? limit ?, ?
    findByIdGreaterThan 3 pageIndex 2 size 3 return: [MoneyPO(id=10, name=batch 一灰灰5, money=1498, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:58.0), MoneyPO(id=11, name=batch 一灰灰6, money=1498, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:58.0), MoneyPO(id=12, name=batch 一灰灰7, money=400, isDeleted=0, createAt=2019-04-18 17:01:40.0, updateAt=2019-04-18 17:01:40.0)]
    

    4. 小结

    主要介绍了jpa的查询的最基本使用方式,主要是根据规则定义方法名的方式来实现sql的效果, 下表示一个简单的对比小结

    方法名 说明 等效sql
    findByXxx 表示根据列Xxx等于传参构建sql where xxx= ?
    findByXxxAndYyy 根据多个列进行查询 where xxx=? and yyy=?
    findByXxxOrYyy 根据多个列实现or查询 where xxx=? or yyy=?
    findByXxxLike like查询,需要注意查询条件中加% where xxx like
    findByXxxIn in查询 where Xxx in ()
    findByXxxGreaterThan 大于 where xxx > ?
    findByXxxGreaterThanEqual 大于等于 where xxx >= ?
    findByXxxLessThan 小于 where xxx < ?
    findByXxxLessThanEqual 小于等于 where xxx <= ?
    findByXxxNot 不等于 where xxx != ?
    findByXxxIsBetween between查询 where xxx between ? and ?
    OrderByXxxDesc 排序 order by xxx desc
    topN 分页,表示获取最前面的n条 limit n

    此外还有一个分页的方式是传参Pageable,来指定具体的分页

    我们常见的查询操作中,除了上面的一些case之外,还有一些是我们没有提到的,如下面的一些使用姿势,则会在后面的文章中引入

    • group by
    • distinct
    • join
    • 各种函数的支持(sum,max,min,avg...)
    • 查询部分表中部分字段时
    • 统计查询

    II. 其他

    0. 源码&相关博文

    源码

    相关博文

    1. 一灰灰Blog

    尽信书则不如,以上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激

    下面一灰灰的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛

    一灰灰blog

    相关文章

      网友评论

        本文标题:SpringBoot系列教程JPA之query使用姿势详解之基础

        本文链接:https://www.haomeiwen.com/subject/hsxasctx.html