查询操作
MP提供了多种查询操作,包括根据id查询 批量查询 查询单条数据 查询列表 分页查询等操作。
根据id查询
方法定义:
/** *根 据 ID 查 询 * *@param id 主键ID */ T selectById(Serializable id);
查询步骤:
根据id查询步骤:
- 设置查询记录的主键值。
- 执行查询。
- 查询结果返回一个对象。
注意:这里返回的就是对象了,之前都是返回影响的行数。
测试用例:
@Test public void testSelectById() { //根据id查询数据 User user = this.userMapper.selectById(2L); System.out.println("result = " + user); }
查询结果:
根据id批量查询
方法定义:
/** *查询(根据ID 批量查询) * *@param idList 主键ID列表(不能为 null 以及 empty) */ List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
查询步骤:
根据id列表查询:
- 设置id列表
- 执行查询
- 查询对象返回List
注意:这里返回的就是对象list了
测试案例:
@Test public void testSelectBatchIds() { //根据id集合批量查询 List<User> users = this.userMapper.selectBatchIds(Arrays.asList(2L, 3L, 10L)); for (User user : users) { System.out.println(user); } }
查询结果:
根据 entity 条件查询一条记录
方法定义:
/** *根据 entity 条件,查询一条记录 * *@param queryWrapper 实体对象封装操作类(可以为 null) */ T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
查询步骤:
- 设置QueryWrapper对象,设置查询条件,可以设置多个条件
- 执行查询
注意:如果查询结果为多条记录则报错(TooManyResultsException)。
测试案例:
@Test public void testSelectOne(){ QueryWrapper<User> queryWrapper =new QueryWrapper<>(); queryWrapper.eq("name","张三"); //根据条件查询,只能查询出一条记录,否则报错 User user = userMapper.selectOne(queryWrapper); System.out.println(user); }
查询结果:
根据 Wrapper 条件查询总记录数
方法定义:
/** *根据 Wrapper 条件,查询总记录数 * *@param queryWrapper 实体对象封装操作类(可以为 null) */ Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
测试案例:
@Test public void testSelectCount() { QueryWrapper<User> wrapper = new QueryWrapper<User>(); wrapper.gt("age", 23); //年龄大于23岁 //根据条件查询数据条数 Integer count = this.userMapper.selectCount(wrapper); System.out.println("count = " + count); }
运行结果为:count = 2
点进gt方法的声明类里,还可以看到其的 Wrapper 条件:
根据 entity 条件查询全部记录
方法定义:
/** *根据 entity 条件,查询全部记录 * *@param queryWrapper 实体对象封装操作类(可以为 null) */ List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
测试案例:
@Test public void testSelectList() { QueryWrapper<User> wrapper = new QueryWrapper<User>(); wrapper.gt("age", 23); //年龄大于23岁 // 根据条件查询数据 List<User> users = this.userMapper.selectList(wrapper); for (User user : users) { System.out.println("user = " + user); } }
运行结果为:
根据 entity 条件查询全部记录(并翻页)
方法定义:
/** *根据 entity 条件,查询全部记录(并翻页) * *@param page 分页查询条件(可以为 RowBounds.DEFAULT) *@param queryWrapper 实体对象封装操作类(可以为 null) */ IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
测试案例:
@Test public void testSelectPage() { //条件 QueryWrapper<User> queryWrapper = new QueryWrapper<>(); // queryWrapper.eq("name","张三");//等于 queryWrapper.gt("age", 20);//大于? //用构造方法设置当前页码,每页记录数 int pageIndex = 2;//当前页码 int size = 3;//每页记录数 Page<User> page = new Page<>(pageIndex, size); IPage<User> userIPage = userMapper.selectPage(page, queryWrapper); // 打印一下记录信息 long pages = userIPage.getPages();//总页数 long total = userIPage.getTotal();//总记录数 System.out.println("数据总条数 :" + total); System.out.println("总页数:" + pages); //记录列表 List<User> records = userIPage.getRecords(); System.out.println(records); }
运行结果:
2022-03-23 21:14:39.335 DEBUG 138796 --- [ main] c.b.m.e.p.p.o.JsqlParserCountOptimize : JsqlParserCountOptimize sql=SELECT id,user_name,password,name,age,email,birthday FROM tb_user WHERE age > ? 2022-03-23 21:14:39.372 DEBUG 138796 --- [ main] c.i.mp.mapper.UserMapper.selectPage : ==> Preparing: SELECT COUNT(1) FROM tb_user WHERE age > ? 2022-03-23 21:14:39.402 DEBUG 138796 --- [ main] c.i.mp.mapper.UserMapper.selectPage : ==> Parameters: 20(Integer) 2022-03-23 21:14:39.558 DEBUG 138796 --- [ main] c.i.mp.mapper.UserMapper.selectPage : ==> Preparing: SELECT id,user_name,password,name,age,email,birthday FROM tb_user WHERE age > ? LIMIT ?,? 2022-03-23 21:14:39.559 DEBUG 138796 --- [ main] c.i.mp.mapper.UserMapper.selectPage : ==> Parameters: 20(Integer), 3(Long), 3(Long) 2022-03-23 21:14:39.715 DEBUG 138796 --- [ main] c.i.mp.mapper.UserMapper.selectPage : <== Total: 3 2022-03-23 21:14:39.716 DEBUG 138796 --- [ main] org.mybatis.spring.SqlSessionUtils : Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7fd987ef] 数据总条数 :6 总页数:2 [User(id=5, userName=sunqi, password=123456, name=孙七, age=24, email=test5@itcast.cn, birthday=2022-03-09T00:00), User(id=1506541267385905153, userName=caocao, password=12222, name=曹操, age=999, email=null, birthday=null), User(id=1506541407249121282, userName=caocao, password=12222, name=曹操, age=999, email=null, birthday=null)]
条件构造器
在MP中,Wrapper接口的实现类关系如下:
在MP查询中,还可以使用lambda方式查询,降低数据库列表写错的风险。
Wrapper中基本比较操作
测试案例:
@Test public void testEqCp() { QueryWrapper<User> wrapper = new QueryWrapper<>(); //SELECT id,user_name,password,name,age,email FROM tb_user WHERE password = ? AND age >= ? AND name IN (?,?,?) wrapper.eq("password", "123456") .ge("age", 20) .in("name", "李四", "王五", "赵六"); List<User> users = this.userMapper.selectList(wrapper); for (User user : users) { System.out.println(user); } }
也可以用Lambda方式构造条件:
@Test public void testEqCp() { LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>(); //SELECT id,user_name,password,name,age,email FROM tb_user WHERE password = ? AND age >= ? AND name IN (?,?,?) wrapper.eq(User::getPassword, "123456") .ge(User::getAge, 20) .in(User::getName, "李四", "王五", "赵六"); List<User> users = this.userMapper.selectList(wrapper); for (User user : users) { System.out.println(user); } }
上面是最简单的查询方法,通常在开发中要根据表达式进行判断,表达式为true则拼接条件,如下:
eq(boolean condition, R column, Object val) in(boolean condition, R column, Object... values) ...
上面代码中的condition就是要进行计算的表达式,最终表达式结果为boolean类型。
举个例子:
比如根据name来判断,如果name不为空则拼接条件 String name = null;
wrapper.eq(User::getPassword, "123456") .ge(User::getAge, 20) .in(name!=null,User::getName, "李四", "王五", "赵六");
下面那个具体的案例,条件查询测试案例:
@Test public void testEq3() { //条件 LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>(); String name = null; Integer age = 20; queryWrapper.eq(name != null && !name.equals(""), User::getName, name);//等于 queryWrapper.gt(age != null, User::getAge, age);//大于? List<User> users = userMapper.selectList(queryWrapper); System.out.println(users); }
模糊查询
like :
LIKE '%值%' 例: like("name", "王") ---> name like '%王%'
notLike:
NOT LIKE '%值%' 例: notLike("name", "王") ---> name not like '%王%'
likeLeft :
LIKE '%值' 例: likeLeft("name", "王") ---> name like '%王'
likeRight :
LIKE '值%' 例: likeRight("name", "王") ---> name like '王%'
测试案例:
@Test public void testWrapper() { QueryWrapper<User> wrapper = new QueryWrapper<>(); //SELECT id,user_name,password,name,age,email FROM tb_user WHERE name LIKE ? //Parameters: %曹%(String) wrapper.likeRight("name", "曹"); wrapper.select("id", "name","birthday"); List<User> users = this.userMapper.selectList(wrapper); for (User user : users) { System.out.println(user); } }
运行结果为:
逻辑查询
or
拼接 OR 主动调用 or 表示紧接着下一个**方法**不是用 and 连接!(不调用 or 则默认为使用 and 连接)
and
AND 嵌套 例: and(i -> i.eq("name", "李白").ne("status", "活着")) ---> and (name = '李白' and status <> '活着')
测试案例:
@Test public void testOr() { QueryWrapper<User> wrapper = new QueryWrapper<>(); //SELECT id,user_name,password,name,age,email FROM tb_user WHERE name = ? OR age = ? wrapper.eq("name", "李四").or().eq("age", 24); //变为and方式 wrapper.eq("name", "李四").eq("age", 24); List<User> users = this.userMapper.selectList(wrapper); for (User user : users) { System.out.println(user); } }
将上面代码改为lambda方式构造条件:
@Test public void testOr() { LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>(); //SELECT id,user_name,password,name,age,email FROM tb_user WHERE name = ? OR age = ? wrapper.eq(User::getName,"李四").or().eq(User::getAge, 24); //变为and方式 wrapper.eq(User::getName, "李四").eq(User::getAge", 24); List<User> users = this.userMapper.selectList(wrapper); for (User user : users) { System.out.println(user); } }
select
在MP查询中,默认查询所有的字段,如果有需要也可以通过select方法进行指定字段。
测试案例:
@Test public void testWrapper() { QueryWrapper<User> wrapper = new QueryWrapper<>(); //SELECT id,name,age FROM tb_user WHERE name = ? OR age = ? wrapper.eq("name", "李四") .or() .eq("age", 24) .select("id", "name", "age"); List<User> users = this.userMapper.selectList(wrapper); for (User user : users) { System.out.println(user); } }
Lambda方式构造条件:
LambdaQueryWrapper<User> w
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>(); wrapper.eq(User::getName, "李四") .or() .eq(User::getAge, 24) .select(User::getId, User::getName, User::getAge);
排序
orderByAsc :升序排序
参数:变长数组,设置多个字段名 例: orderByAsc("id", "name") ---> order by id ASC,name ASC
orderByDesc :降序排序
参数:变长数组,设置多个字段名 例: orderByDesc("id", "name") ---> order by id DESC,name DESC
orderBy : 自定义排序规则
方法定义:orderBy(boolean condition, boolean isAsc, R... columns) 参数1:true有效,false无效 ,参数2:是否升序,参数3..设置多个字段 例: `orderBy(true, true, "id", "name")`‐‐‐>`order by id ASC,name ASC`
也可以多个orderBy拼装,如下:
orderBy(true, true, "id").orderBy(true, true, "name")
效果同上面语句。
测试案例:
@Test public void testOrder() { QueryWrapper<User> wrapper = new QueryWrapper<>(); //SELECT id,user_name,password,name,age,email FROM tb_user ORDER BY age DESC wrapper.orderByDesc("age"); List<User> users = this.userMapper.selectList(wrapper); for (User user : users) { System.out.println(user); } }
Lambda方式构造条件:
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>(); wrapper.orderByDesc(User::getAge);