pom里面添加: <!--mybatis-plus--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.3.1</version> </dependency> yml添加: # 数据源 spring: datasource: username: root password: root url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8 driver-class-name: com.mysql.jdbc.Driver
创建包 mapper 编写Mapper 接口: public interface UserMapper extends BaseMapper<User> { interface UserMapper extends BaseMapper<User> { ........... } 在 Spring Boot 启动类中添加
@MapperScan
注解,扫描 Mapper 文件夹: 例如: @SpringBootApplication @MapperScan("com.zx.mapper") public class MybatisPlusApplication { ...... }
1、ASSIGN_ID
MyBatis-Plus默认的主键策略是:ASSIGN_ID (使用了雪花算法)
小项目我们用自增
AUTO 自增策略
实体上增加字段并添加自动填充注解
@Data public class User { ...... @TableField(fill = FieldFill.INSERT) private Date createTime;
//@TableField(fill = FieldFill.UPDATE) @TableField(fill = FieldFill.INSERT_UPDATE) private Date updateTime; }
实现MetaObjectHandler接口 重写 insertFill 和 updateFill 不要忘记@Component | 这里的数据库是datetime类型 然后在实体类里面写 Date类型
package com.zx
@Slf4j @Component public class MyMetaObjectHandler implements MetaObjectHandler {
@Override public void insertFill(MetaObject metaObject) { log.info("start insert fill ...."); this.setFieldValByName("createTime", new Date(), metaObject); this.setFieldValByName("updateTime", new Date(), metaObject); }
@Override public void updateFill(MetaObject metaObject) { log.info("start update fill ...."); this.setFieldValByName("updateTime", new Date(), metaObject); } }
1、场景 一件商品,成本价是80元,售价是100元。老板先是通知小李,说你去把商品价格增加50元。小李正在玩游戏,耽搁了一个小时。正好一个小时后,老板觉得商品价格增加到150元,价格太高,可能会影响销量。又通知小王,你把商品价格降低30元。 此时,小李和小王同时操作商品后台系统。小李操作的时候,系统先取出商品价格100元;小王也在操作,取出的商品价格也是100元。小李将价格加了50元,并将100+50=150元存入了数据库;小王将商品减了30元,并将100-30=70元存入了数据库。是的,如果没有锁,小李的操作就完全被小王的覆盖了。 现在商品价格是70元,比成本价低10元。几分钟后,这个商品很快出售了1千多件商品,老板亏1多万。 2、乐观锁与悲观锁
乐观锁实现流程 (1)修改实体类 添加 @Version 注解 @Version private Integer version; (2)创建配置文件 创建包config,创建文件MybatisPlusConfig.java 此时可以删除主类中的 @MapperScan 扫描注解 package com.zx.config; @EnableTransactionManagement @Configuration @MapperScan("com.zx.mapper") public class MybatisPlusConfig { } (3)注册乐观锁插件 在 MybatisPlusConfig 中注册 Bean /** * 乐观锁插件 */ @Bean public OptimisticLockerInterceptor optimisticLockerInterceptor() { return new OptimisticLockerInterceptor(); }
@Test public void testSelectBatchIds(){ List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3)); users.forEach(System.out::println); }
通过map封装查询条件
注意:map中的key对应数据库中的列名。如:数据库user_id,实体类是userId,这时map的key需要填写user_id
@Test public void testSelectByMap(){ HashMap<String, Object> map = new HashMap<>(); map.put("name", "Helen"); map.put("age", 18); List<User> users = userMapper.selectByMap(map); users.forEach(System.out::println); }
MyBatis Plus自带分页插件,只要简单的配置即可实现分页功能
(1)添加分页插件
配置类中添加@Bean配置
/** * 分页插件 */ @Bean public PaginationInterceptor paginationInterceptor() { return new PaginationInterceptor(); }
(2)selectPage实现分页
@Test public void testSelectPage() { Page<User> page = new Page<>(1,5); Page<User> pageParam = userMapper.selectPage(page, null); pageParam.getRecords().forEach(System.out::println); System.out.println(pageParam.getCurrent()); System.out.println(pageParam.getPages()); System.out.println(pageParam.getSize()); System.out.println(pageParam.getTotal()); System.out.println(pageParam.hasNext()); System.out.println(pageParam.hasPrevious()); }
返回指定列
Page<Map<String, Object>> page = new Page<>(1, 5); QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.select("name", "age"); Page<Map<String, Object>> pageParam = userMapper.selectMapsPage(page, queryWrapper); List<Map<String, Object>> records = pageParam.getRecords(); records.forEach(System.out::println); System.out.println(pageParam.getCurrent()); System.out.println(pageParam.getPages()); System.out.println(pageParam.getSize()); System.out.println(pageParam.getTotal()); System.out.println(pageParam.hasNext()); System.out.println(pageParam.hasPrevious());
逻辑删除
1 添加 deleted字段
2 添加deleted 字段,并加上 @TableLogic 注解
@TableLogic private Integer deleted;
3配置(可选)application.properties 加入以下配置,此为默认值,如果你的默认值和mp默认的一样,该配置可无
mybatis-plus.global-config.db-config.logic-delete-value=1 mybatis-plus.global-config.db-config.logic-not-delete-value=0
@Test public void testDeleteById(){ int result = userMapper.deleteById(5L); System.out.println(result); }
@Test public void testDeleteBatchIds() { int result = userMapper.deleteBatchIds(Arrays.asList(8, 9, 10)); System.out.println(result); }
@Test public void testDeleteByMap() { HashMap<String, Object> map = new HashMap<>(); map.put("name", "Helen"); map.put("age", 18); int result = userMapper.deleteByMap(map); System.out.println(result); }
Wrapper : 条件构造抽象类,最顶端父类 AbstractWrapper : 用于查询条件封装,生成 sql 的 where 条件 QueryWrapper : 查询条件封装 UpdateWrapper : Update 条件封装 AbstractLambdaWrapper : 使用Lambda 语法 LambdaQueryWrapper :用于Lambda语法使用的查询Wrapper LambdaUpdateWrapper : Lambda 更新封装Wrapper
查询方式 说明
setSqlSelect 设置 SELECT 查询字段
where WHERE 语句,拼接 + WHERE 条件
and AND 语句,拼接 + AND 字段=值
andNew AND 语句,拼接 + AND (字段=值)
or OR 语句,拼接 + OR 字段=值
orNew OR 语句,拼接 + OR (字段=值)
eq 等于=
allEq 基于 map 内容等于=
ne 不等于<>
gt 大于>
ge 大于等于>=
lt 小于<
le 小于等于<= like 模糊查询 LIKE notLike 模糊查询 NOT LIKE
in IN 查询
notIn NOT IN 查询
isNull NULL 值查询
isNotNull IS NOT NULL
groupBy 分组 GROUP BY
having HAVING 关键词
orderBy 排序 ORDER BY
orderAsc ASC 排序 ORDER BY
orderDesc DESC 排序 ORDER BY
exists EXISTS 条件语句
notExists NOT EXISTS 条件语句
between BETWEEN 条件语句
notBetween NOT BETWEEN 条件语句
addFilter 自由拼接 SQL
last 拼接在最后,例如:last(“LIMIT 1”)
Test public void testDelete() { QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper .isNull("name") .ge("age", 12) .isNotNull("email"); int result = userMapper.delete(queryWrapper); System.out.println("delete return count = " + result); }
注意:seletOne()返回的是一条实体记录,当出现多条时会报错
@Test public void testSelectOne() { QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("name", "张旭");
User user = userMapper.selectOne(queryWrapper);//只能返回一条记录,多余一条则抛出异常 System.out.println(user); }
@Test public void testSelectCount() { QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.between("age", 20, 30); Integer count = userMapper.selectCount(queryWrapper); //返回数据数量 System.out.println(count); }
selectMaps()返回Map集合列表,通常配合select()使用
@Test public void testSelectMaps() { QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper .select("name", "age") .like("name", "e") .likeRight("email", "5"); List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);//返回值是Map列表 maps.forEach(System.out::println); }
in、notIn:
notIn("age",{1,2,3})--->age not in (1,2,3)
notIn("age", 1, 2, 3)--->age not in (1,2,3)
inSql、notinSql:可以实现子查询
inSql("age", "1,2,3,4,5,6")
--->age in (1,2,3,4,5,6)
inSql("id", "select id from table where id < 3")
--->id in (select id from table where id < 3)
@Test public void testSelectObjs() { QueryWrapper<User> queryWrapper = new QueryWrapper<>(); // queryWrapper.in("id", 1, 2, 3); queryWrapper.inSql("id", "select id from user where id <= 3"); List<Object> objects = userMapper.selectObjs(queryWrapper);//返回值是Object列表 objects.forEach(System.out::println); }
注意:这里使用的是 UpdateWrapper
不调用or
则默认为使用 and
连接
@Test public void testUpdate1() { //修改值 User user = new User(); user.setAge(99); user.setName("Andy"); //修改条件 UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>(); userUpdateWrapper .like("name", "h") .or() .between("age", 20, 30); int result = userMapper.update(user, userUpdateWrapper); System.out.println(result); }
lambda表达式内的逻辑优先运算
@Test public void testUpdate2() { //修改值 User user = new User(); user.setAge(99); user.setName("Andy"); //修改条件 UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>(); userUpdateWrapper .like("name", "n") .or(i -> i.like("name", "a").eq("age", 20)); int result = userMapper.update(user, userUpdateWrapper); System.out.println(result); }
@Test public void testSelectListOrderBy() { QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.orderByDesc("age", "id"); List<User> users = userMapper.selectList(queryWrapper); users.forEach(System.out::println); }
最终的sql会合并 user.setAge(),以及 userUpdateWrapper.set() 和 setSql() 中 的字段
@Test public void testUpdateSet() { //修改值 User user = new User(); user.setAge(60); //修改条件 UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>(); userUpdateWrapper .like("name", "h") .set("name", "Peter")//除了可以查询还可以使用set设置修改的字段 .setSql(" email = '123@qq.com'");//可以有子查询 int result = userMapper.update(user, userUpdateWrapper); }