条件构造器
一般都是用service层的方法,因为比mapper层的全。十分重要:Wrapper 记住查看输出的SQL进行分析
相当于创建一个构造器对象,然后讲需要查询or更新的条件写在里面,最后打包给mapper or service层的插入、更新方法
下图是Wapper的子类,QueryWrapper和UpdateWrapper是一般的Wrapper,AbstractLambdaWrapper 是lambda语法糖的链式操作(两者选择一种使用即可)
![MybatisPlus核心功能——实现CRUD增删改查操作 (包含条件构造器)](https://p3.toutiaoimg.com/origin/tos-cn-i-qvj2lq49k0/528298993fae4bf2b128095ada0a3d6a.jpg)
下图是wrapper的条件方法,就不一一介绍了,下面举了六个就基本例子
![MybatisPlus核心功能——实现CRUD增删改查操作 (包含条件构造器)](https://p3.toutiaoimg.com/origin/tos-cn-i-qvj2lq49k0/48d28d75e414437c986638e914b0ec06.jpg)
1、测试一
@Testpublic void testWrapper1() { //参数是一个wrapper ,条件构造器,和刚才的map对比学习! //查询name不为空,email不为空,age大于18的用户 QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper .isNotNull("name") .isNotNull("email") .ge("age",18); List<User> userList = userMapper.selectList(wrapper); userList.forEach(System.out::println);}
测试二
@Testpublic void testWrapper2() { //查询name=wsk的用户 QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.eq("name","wsk"); //查询一个数据selectOne,若查询出多个会报错 //Expected one result (or null) to be returned by selectOne(), but found: * //若出现多个结果使用list或map User user = userMapper.selectOne(wrapper);//查询一个数据,若出现多个结果使用list或map System.out.println(user);}
测试三
@Testpublic void testWrapper3() { //查询age在10-20之间的用户 QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.between("age", 10, 20);//区间 Integer count = userMapper.selectCount(wrapper);//输出查询的数量selectCount System.out.println(count);}
测试四
@Testpublic void testWrapper4() { //模糊查询 QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper .notLike("name","s") .likeRight("email","qq");//qq% 左和右? List<Map<String, Object>> maps = userMapper.selectMaps(wrapper); maps.forEach(System.out::println);}
测试五
@Testpublic void testWrapper5() { //模糊查询 // SELECT id,name,age,email,version,deleted,create_time,update_time //FROM user //WHERE deleted=0 AND id IN //(select id from user where id<5) QueryWrapper<User> wrapper = new QueryWrapper<>(); //id 在子查询中查出来 wrapper.inSql("id","select id from user where id<5"); List<Object> objects = userMapper.selectObjs(wrapper); objects.forEach(System.out::println);}
测试六
@Testpublic void testWrapper6() { QueryWrapper<User> wrapper = new QueryWrapper<>(); //通过id进行降序排序 wrapper.orderByDesc("id"); List<User> userList = userMapper.selectList(wrapper); userList.forEach(System.out::println);}
CRUD接口
基本配置:
0、创建数据库
DROP TABLE IF EXISTS user;CREATE TABLE user( id BIGINT(20) NOT NULL COMMENT '主键ID', name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名', age INT(11) NULL DEFAULT NULL COMMENT '年龄', email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱', version INT(10) NOT NULL DEFAULT 1 COMMIT '乐观锁版本号', DELETED INT(10) NOT NULL DEFAULT 0 COMMIT '逻辑删除', CREATE_TIME DATE COMMIT '创建时间', modify_time DATE COMMIT '更新时间', PRIMARY KEY (id));DELETE FROM user;INSERT INTO user (id, name, age, email) VALUES(1, '工藤新一','[email protected]'),(2, '毛利兰','[email protected]'),(3, '柯南', 28, '[email protected]'),(4, '灰原哀', 21, '[email protected]'),(5, '工藤有希子', 24, '[email protected]');
1、创建项目,导入依赖
<!--spring-boot--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--SpringBootTest--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!--lombok--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <!--mysql 驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.26</version> </dependency> <!--mybatis-plus--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.2</version> </dependency>
2、yaml
#设置开发环境spring: datasource: username: root password: 123456 driver-class-name: com.p6spy.engine.spy.P6SpyDriver url: jdbc:p6spy:mysql://localhost:3306/mybatis_plus?serverTimezone=UTC&useUnicode=true&characterEncoding=utf#配置日志 log-impl:日志实现mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
3、创建实体类
@Data@AllArgsConstructor@NoArgsConstructor@TableName("user")public class User { @TableId(type = IdType.AUTO) Long id; String name; int age; String email; @Version//乐观锁version注解 private Integer version; private Integer isDelete; @TableField(fill = FieldFill.INSERT) private Date cTime; @TableField(fill = FieldFill.INSERT_UPDATE) private Date upTime;}
4、写Mapper
@Repositorypublic interface UserMapper extends BaseMapper<User> {}
5、写Service接口和实现类
//Service接口public interface UserService extends IService<User> { //别忘了继承这个父类}//实现类@Servicepublic class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService { //记得继承父类}
6、之后就可以测试了
Mapper CRUD接口
顾名思义这个只有mapper层对象才有的方法
Insert
写数据库的时候id设置了主键自增的话,插入的时候不需要加入id,因为MP会自动添加并且自增的。
注:数据库写了id自增的话,在实体类设置主键生成策略是没用的,因为数据库设置了自增,数据库优先级高于代码
@Test//测试插入public void insertTest(){ User user = new User(); user.setName("wsk"); user.setAge(18); user.setEmail("[email protected]"); Integer result = userMapper.insert(user); //会帮我们自动生成id System.out.println(result); //受影响的行数 System.out.println(user); //通过日志发现id会自动回填(id是由雪花算法生成的,在主键生成策略部分有讲到)}
![MybatisPlus核心功能——实现CRUD增删改查操作 (包含条件构造器)](https://p3.toutiaoimg.com/origin/tos-cn-i-qvj2lq49k0/2a9ad964dfb54a0e8bb1de3fbe28814a.jpg)
数据库插入的id的默认值为:全局的唯—id
Update
@Test//测试更新public void updateTest(){ User user = new User(); user.setId(2L);//怎么改id?? //通过条件自动拼接动态Sql user.setName("root"); user.setAge(12); user.setEmail("[email protected]"); int i = userMapper.updateById(user);//updateById,但是参数是个user System.out.println(i);}
![MybatisPlus核心功能——实现CRUD增删改查操作 (包含条件构造器)](https://p3.toutiaoimg.com/origin/tos-cn-i-qvj2lq49k0/9d71d8033a6d406dacfd4160a28b9658.jpg)
Select
- 通过id查询单个用户
@Test//通过id查询单个用户public void testSelectById(){ User user = userMapper.selectById(1L); System.out.println(user);}
![MybatisPlus核心功能——实现CRUD增删改查操作 (包含条件构造器)](https://p3.toutiaoimg.com/origin/tos-cn-i-qvj2lq49k0/b35c96ff0bd3446498565fee7316d22e.jpg)
- 通过id查询多个用户
@Test//通过id查询多个用户public void testSelectBatchIds(){ List<User> users = userMapper.selectBatchIds(Arrays.asList(1L, 2L, 3L)); users.forEach(System.out::println); //System.out.println(users);}
![MybatisPlus核心功能——实现CRUD增删改查操作 (包含条件构造器)](https://p3.toutiaoimg.com/origin/tos-cn-i-qvj2lq49k0/084de8c198f64f898595cfa994baf258.jpg)
![MybatisPlus核心功能——实现CRUD增删改查操作 (包含条件构造器)](https://p3.toutiaoimg.com/origin/tos-cn-i-qvj2lq49k0/0ee061e9b7b74d1eb783fca13e8187f4.jpg)
- 条件查询 通过map封装
@Test//通过条件查询之一 map(这里的map,相当于where后面的 name="conan"等条件)public void testMap(){ HashMap<String, Object> map = new HashMap<>(); //自定义要查询的 map.put("name","www"); //查询名字是www的数据 map.put("name","111"); //查询名字是111的数据 最后的结果是取两者交集 map.put("age",18); List<User> users = userMapper.selectByMap(map); users.forEach(System.out::println);}
![MybatisPlus核心功能——实现CRUD增删改查操作 (包含条件构造器)](https://p3.toutiaoimg.com/origin/tos-cn-i-qvj2lq49k0/d751f7c9d4e942c9b2c8ffa421b4dad4.jpg)
![MybatisPlus核心功能——实现CRUD增删改查操作 (包含条件构造器)](https://p3.toutiaoimg.com/origin/tos-cn-i-qvj2lq49k0/45ef4e2755f141ab8940275b5680ba2e.jpg)
Delete
基本的删除任务:
![MybatisPlus核心功能——实现CRUD增删改查操作 (包含条件构造器)](https://p3.toutiaoimg.com/origin/tos-cn-i-qvj2lq49k0/93a4af13197745e898ff05e45c35abc0.jpg)
@Testpublic void testDeleteById(){ userMapper.deleteById(1359507762519068681L);}@Testpublic void testDeleteBatchIds(){ userMapper.deleteBatchIds(Arrays.asList(1359507762519068675L,1359507762519068676L));}@Testpublic void testD(){ HashMap<String, Object> map = new HashMap<>(); map.put("age","18"); map.put("name","lol"); userMapper.deleteByMap(map);}
Service CRUD接口
顾名思义这是Service层才有的方法
Save
为了区分mapper层和service层的方法,所以service层的插入方法取名为save
@Testvoid test(){ User user = new User(); user.setName("Conan"); user.setAge(18); user.setEmail("毛利侦探事务所"); //插入单条数据 userService.save(user); // 插入(批量) userService.saveBatch(Arrays.asList(user));}
Remove
service层删除方法取名为remove
@Test void test(){ User user = new User(); user.setName("Conan"); user.setAge(18); user.setEmail("毛利侦探事务所"); HashMap<String,Object> map = new HashMap<>(); map.put("name","Conan"); QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.eq("name","毛利小五郎"); userService.remove(wrapper); //根据条件构造器删除数据 userService.removeById(16L); //根据id删除数据,也可以根据实体类对象删除数据 userService.removeByMap(map); //根据map的条件删除记录 userService.removeBatchByIds(Arrays.asList(user)); //批量删除 }
Update
@Test void test(){ User user = new User(); user.setName("Conan"); user.setAge(18); user.setEmail("毛利侦探事务所"); HashMap<String,Object> map = new HashMap<>(); map.put("name","Conan"); QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.eq("name","毛利小五郎") .ge("age",18); userService.update(wrapper); //根据条件构造器更新 userService.updateById(user); //根据传入的实体类id确定需要更新的数据,更新为传入的实体类对象 userService.updateBatchById(Arrays.asList(user)); //批量更新 }
Get
该方法只能查询一条数据,所以不推荐。查询用list方法
@Test void test(){ User user = new User(); user.setName("Conan"); user.setAge(18); user.setEmail("毛利侦探事务所"); HashMap<String,Object> map = new HashMap<>(); map.put("name","Conan"); QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.eq("name","毛利小五郎") .ge("age",18); userService.getById(12L); //根据id查询一条数据 userService.getMap(wrapper); //根据构造器查询一条数据,返回Mapper集合 }
List
查询多条数据
@Testvoid test(){ User user = new User(); user.setName("Conan"); user.setAge(18); user.setEmail("毛利侦探事务所"); HashMap<String,Object> map = new HashMap<>(); map.put("name","Conan"); QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.eq("name","毛利小五郎") .ge("age",18); userService.list(); //查询全部数据 userService.listMaps(); //查询全部数据,以map形式返回 userService.listByMap(map); //根据map查询数据 userService.listByIds(Arrays.asList(10L,15L)); //根据id查询数据}
SaveOrUpdate
运行逻辑:直接更新,更新0行的话;就select,查询出来是0行;则就插入
有传入id的情况会优先更新,如果更新不了,则会插入新的数据
记得在实体类写上@TableId!!!
@Testvoid test(){ User user = new User(); user.setName("Conan"); user.setAge(18); user.setEmail("毛利侦探事务所"); HashMap<String,Object> map = new HashMap<>(); map.put("name","Conan"); UpdateWrapper<User> wrapper = new UpdateWrapper<>(); wrapper.eq("name","毛利小五郎") .ge("age",18); userService.saveOrUpdate(user); //传入的对象id存在则更新,否则插入新数据 userService.saveOrUpdate(user,wrapper); //根据更新条件构造器,更细数据 userService.saveOrUpdateBatch(Arrays.asList(user)); //批量修改插入}
Count
统计符合条件的数据的数量
@Test void test(){ User user = new User(); user.setName("Conan"); user.setAge(18); user.setEmail("毛利侦探事务所"); HashMap<String,Object> map = new HashMap<>(); map.put("name","Conan"); QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.eq("name","毛利小五郎") .ge("age",18); userService.count(); userService.count(); }
Chain
链式调用,可以不用条件构造器完成 条件设置和增删改查。推荐!因为优雅!
Query
@Testvoid test(){ User user = new User(); user.setName("Conan"); user.setAge(18); user.setEmail("毛利侦探事务所"); HashMap<String,Object> map = new HashMap<>(); map.put("name","Conan"); QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.eq("name","毛利小五郎") .ge("age",18); List<User> userList = userService.query() .eq("name", "工藤新一") .gt("age", 17) .list(); for(User user01: userList) { System.out.println(user); }}
Update
@Testvoid test(){ User user = new User(); user.setName("Conan"); user.setAge(18); user.setEmail("毛利侦探事务所"); HashMap<String,Object> map = new HashMap<>(); map.put("name","Conan"); QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.eq("name","毛利小五郎") .ge("age",18); userService.update() .eq("name", "工藤新一") .gt("age", 17) .update();}