MyBatis-Plus 学习笔记
MyBatis-Plus 学习笔记
学习官网: https://mp.baomidou.com/guide/
一、快速入门
1.简介
- MyBatis的增强工具,在Mybatis的基础上只做增强功能,兼容MyBatis
我们的愿景是成为 MyBatis 最好的搭档,就像 魂斗罗 中的 1P、2P,基友搭配,效率翻倍。
2.快速开始
2.1 官方提供的数据库的表
创建表:
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 '邮箱',PRIMARY KEY (id)
);
插入数据:
DELETE FROM user;INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');
表:
2.2 创建spring boot项目
2.3 引入依赖
除了创建项目引入的那些常用的依赖外,还需要引入mybatis-plus和mysql驱动的依赖
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.2</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.49</version></dependency>
2.4 配置
yml配置
spring:datasource:url: jdbc:mysql://localhost:3306/bookstoredriver-class-name: com.mysql.jdbc.Driverusername: rootpassword: '073838'
2.5 编写bean和mapper
User:
@Data
public class User {private Long id;private String name;private Integer age;private String email;
}
UserMapper:
@Mapper//也可以在springboot主类上标@MapperScan注解
public interface UserMapper extends BaseMapper<User> {}
2.6 开始使用
使用测试类进行测试:
@SpringBootTest
class MpApplicationTests {@Autowiredprivate UserMapper userMapper;@Testpublic void testSelect() {System.out.println(("----- selectAll method test ------"));List<User> userList = userMapper.selectList(null);for (User user: userList){System.out.println(user);}}}
运行结果:
3.常用注解
@TableName
描述:表名注解,标在实体类中
常用属性:
- value:表名
- schema:对应的schema
- resultMap:sql映射文件中 resultMap 的 id
使用:
@Data
@TableName(value = "user", schema = "bookstore", resultMap = "book")
public class User {private Long id;private String name;private Integer age;private String email;
}
注意:resultMap 若使用,需要编写相应的sql映射文件来映射,否则会报错
@TableId
描述:主键注解
属性:
IdType:设置自动生成主键值的策略
@TableField
描述:字段注解(非主键)
属性:详见https://mp.baomidou.com/guide/annotation.html#tablefield
- value:数据库字段名
- el:映射为原生
#{ ... }
逻辑,相当于写在 xml 里的#{ ... }
部分 - exist:是否为数据库表字段。若为false,该属性不会映射到数据库表的字段
示例:
@TableName(value = "user", schema = "bookstore")
public class User {@TableId(value = "id")private Long id;@TableField(exist = true, value = "email")private String name;private Integer age;private String email;
}
运行结果:
@Version注解
描述:乐观锁注解、标记,标记@Version在字段上
@EnumValue
- 描述:通枚举类注解(注解在枚举字段上)
二、CRUD接口
1.Service CRUD接口
IService提供了给service层进行CRUD的接口,需要配合Mapper层的接口一起使用。主要有save、remove、update、getOne、list等。示例:
@SpringBootTest
public class CRUDTest {@AutowiredUserService userService;@Testpublic void saveTest(){User user = new User();user.setAge(18);user.setEmail("aaaa@126.com");user.setName("anpu");List<User> list = new ArrayList<>();for(int i = 0; i < 15; i++){list.add(user);}userService.save(user);userService.saveBatch(list);}@Testpublic void getTest(){User user = userService.getById("1");List<User> users = userService.list();System.out.println("one:" + user);System.out.println("--------------------");users.forEach(System.out::println);}@Testpublic void updateTest(){User user = userService.getById(6);user.setAge(3);user.setName("deserts");userService.updateById(user);}@Testpublic void deleteTest(){userService.removeById(6);Map<String, Object> map = new HashMap<>();map.put("name", "anpu");userService.removeByMap(map);}@Testpublic void saveOrUpdateTest(){User user = userService.getById(3);user.setName("lala");user.setId(6L);userService.saveOrUpdate(user);}@Testpublic void countTest(){System.out.println(userService.count());}}
2.Mapper CRUD层接口
BaseMapper提供了Mapper层进行CRUD的接口。主要有delete、select、update、Insert接口。
3.两层CRUD接口的使用
1.Mapper层接口继承BaseMapper接口
@Mapper
public interface UserMapper extends BaseMapper<User> {}
2.Service层创建接口去继承IService接口
public interface UserService extends IService<User> {}
3.创建service实现类去继承ServiceImpl,实现service接口,妻子ServiceImpl是Iservice的实现类,避免重写很多方法
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {}
三、条件构造器
说明:
QueryWrapper(LambdaQueryWrapper) 和 UpdateWrapper(LambdaUpdateWrapper) 的父类
用于生成 sql 的 where 条件, entity 属性也用于生成 sql 的 where 条件
注意: entity 生成的 where 条件与 使用各个 api 生成的 where 条件没有任何关联行为
AbstractWrapper
AbstractWrapper是抽象类,封装了基本的条件方法,提供给QueryWrapper和UpdateWrapper继承使用。
提供的条件方法:
- allEq, eq, ne:等于(map),等于(单个),不等于
- gt,ge,lt,le: 大于,大于等于,小于,小于等于
- between,notBetween: 在A和B之间,不在A和B之间
- like: 模糊查询。示例: like(“name”, “王”)
--->
name like ‘%王%’ - notLike: 模糊查询。示例: notLike(“name”, “王”)
--->
name not like ‘%王%’ - likeLeft: 模糊查询。示例:likeLeft(“name”, “王”)
--->
name like ‘%王’ - likeRight: 模糊查询。示例:likeRight(“name”, “王”)
--->
name like ‘王%’ - isNull, isNotNUll: 是否为空
- in,notIn: 取值范围
- inSql, notInSql: 子查询。示例:inSql(“id”, “select id from table where id < 3”)
--->
id in (select id from table where id < 3) - groupBy: 分组查询。示例: groupBy(“id”, “name”)
--->
group by id,name - orederByAsc,orederByDsc,orederBy: 按字段升降序排序查找
- having: 示例:having(“sum(age) > 10”)
--->
having sum(age) > 10 - or,and: 条件嵌套。示例:eq(“id”,1).or().eq(“name”,“老王”)
--->
id = 1 or name = ‘老王’ - exists,notExists: 子查询。示例:exists(“select id from table where age = 1”)
--->
exists (select id from table where age = 1)
conditonal参数
如:notExists(boolean condition, String notExistsSql);默认为true,若为false,表示该条件失效。
QueryWrapper
QueryWrapper继承AbstractWrapper。除了AbstractWrapper外,还有select()用于设置查询字段:
select(String... sqlSelect)
select(Predicate<TableFieldInfo> predicate)
select(Class<T> entityClass, Predicate<TableFieldInfo> predicate)
说明:
以上方法分为两类.
第二类方法为:过滤查询字段(主键除外),入参不包含 class 的调用前需要wrapper
内的entity
属性有值! 这两类方法重复调用以最后一次为准
- 例:
select("id", "name", "age")
- 例:
select(i -> i.getProperty().startsWith("test"))
UpdateWrapper
说明:
继承自
AbstractWrapper
,自身的内部属性entity
也用于生成 where 条件
及LambdaUpdateWrapper
, 可以通过new UpdateWrapper().lambda()
方法获取!
set
为某个字段的所以值设置为一个值,如set(“name”, null)--->数据库字段值变为
null
set(String column, Object val)
set(boolean condition, String column, Object val)
setSql
- 设置 SET 部分 SQL
- 例:
setSql("name = '老李头'")
四、分页功能
1.加入分页插件
@Configuration
public class MyBatisConfiguration {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor(){MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();// 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求 默认falsepaginationInnerInterceptor.setOverflow(true);// 设置最大单页限制数量,默认 500 条,-1 不受限制paginationInnerInterceptor.setMaxLimit(100L);mybatisPlusInterceptor.addInnerInterceptor(paginationInnerInterceptor);return mybatisPlusInterceptor;}
}
2.使用service层的接口实现分页
@Testpublic void pageTest(){Page<User> page = new Page<>(1, 5);QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.eq("name", "anpu");Page<User> userPage = userService.page(page, wrapper);List<User> records = userPage.getRecords();System.out.println("---------" + userPage);System.out.println("-------->" + userPage.getTotal());System.out.println("-------->" + userPage.getSize());records.forEach(System.out::println);}
控制台输出:
---------com.baomidou.mybatisplus.extension.plugins.pagination.Page@44114b9f
-------->16
-------->5
User(id=15, name=anpu, age=18, email=aaaa@126.com)
User(id=16, name=anpu, age=18, email=aaaa@126.com)
User(id=17, name=anpu, age=18, email=aaaa@126.com)
User(id=18, name=anpu, age=18, email=aaaa@126.com)
User(id=19, name=anpu, age=18, email=aaaa@126.com)
五、乐观锁插件
MybatisPlusInterceptor
该插件是核心插件,目前代理了 Executor#query
和 Executor#update
和 StatementHandler#prepare
方法
目前已有的功能:
- 自动分页: PaginationInnerInterceptor
- 多租户: TenantLineInnerInterceptor
- 动态表名: DynamicTableNameInnerInterceptor
- 乐观锁: OptimisticLockerInnerInterceptor
- sql性能规范: IllegalSQLInnerInterceptor
- 防止全表更新与删除: BlockAttackInnerInterceptor
使用顺序:
使用多个功能需要注意顺序关系,建议使用如下顺序
- 多租户,动态表名
- 分页,乐观锁
- sql性能规范,防止全表更新与删除
总结: 对sql进行单次改造的优先放入,不对sql进行改造的最后放入
乐观锁实现
什么是乐观锁?当要更新一条记录的时候,希望这条记录没有被别人更新
乐观锁的实现方式:
- 取出记录时,获取当前version
- 更新时,带上这个version
- 执行更新时, set version = newVersion where version = oldVersion
- 如果version不对,就更新失败
使用方法:
1.数据库表添加字段version
2.实体类使用@version标注
@Data
@TableName(value = "user", schema = "bookstore")
public class User {@TableId(value = "id", type = IdType.AUTO)private Long id;private String name;private Integer age;private String email;@Versionprivate Long version;
}
- 支持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime
- 整数类型下
newVersion = oldVersion + 1
newVersion
会回写到entity
中- 仅支持
updateById(id)
与update(entity, wrapper)
方法- 在
update(entity, wrapper)
方法下,wrapper
不能复用!!!
3.配置类加入乐观锁插件,乐观锁生效
@Configuration
public class MyBatisConfiguration {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor(){MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();//分页插件PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();// 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求 默认falsepaginationInnerInterceptor.setOverflow(true);// 设置最大单页限制数量,默认 500 条,-1 不受限制paginationInnerInterceptor.setMaxLimit(100L);//乐观锁插件OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor = new OptimisticLockerInnerInterceptor();mybatisPlusInterceptor.addInnerInterceptor(paginationInnerInterceptor);mybatisPlusInterceptor.addInnerInterceptor(optimisticLockerInnerInterceptor);return mybatisPlusInterceptor;}
}
六、扩展功能
1.代码生成器
添加依赖:MyBatis-Plus 从 3.0.3 之后移除了代码生成器与模板引擎的默认依赖,需要手动添加相关依赖:
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><version>3.4.1</version></dependency><dependency><groupId>org.apache.velocity</groupId><artifactId>velocity-engine-core</artifactId><version>2.3</version></dependency>
编写代码:
@Testpublic void test(){//创建代码生成器AutoGenerator mpg = new AutoGenerator();// 全局配置GlobalConfig gc = new GlobalConfig();String projectPath = System.getProperty("user.dir");gc.setOutputDir(projectPath + "/src/main/java");gc.setEntityName("bean");gc.setMapperName("mapper");gc.setServiceName("service");gc.setControllerName("controller");//是否覆盖之前的文件gc.setFileOverride(true);gc.setAuthor("deserts");gc.setOpen(false);//实体属性 Swagger2 注解gc.setSwagger2(true);mpg.setGlobalConfig(gc);// 数据源配置DataSourceConfig dsc = new DataSourceConfig();dsc.setUrl("jdbc:mysql://localhost:3306/bookstore?useUnicode=true&useSSL=false&characterEncoding=utf8");dsc.setDriverName("com.mysql.jdbc.Driver");dsc.setUsername("root");dsc.setPassword("073838");mpg.setDataSource(dsc);// 包配置PackageConfig pc = new PackageConfig();pc.setModuleName("auto");pc.setParent("com.deserts");mpg.setPackageInfo(pc);// 策略配置StrategyConfig strategy = new StrategyConfig();strategy.setNaming(NamingStrategy.underline_to_camel);strategy.setColumnNaming(NamingStrategy.underline_to_camel);strategy.setEntityLombokModel(true);strategy.setRestControllerStyle(true);//包含的表名strategy.setInclude("user");//设置逻辑删除字段strategy.setLogicDeleteFieldName("deleted");//设置自动填充字段TableFill gmt_create = new TableFill("gmt_create", FieldFill.INSERT);TableFill gmt_update = new TableFill("gmt_update", FieldFill.INSERT_UPDATE);strategy.setTableFillList(Arrays.asList(gmt_create, gmt_update));//设置乐观锁version字段strategy.setVersionFieldName("version");mpg.setStrategy(strategy);//执行mpg.execute();}
2.逻辑删除
1.数据库表中增加一个逻辑删除的字段:
2.配置yml
mybatis-plus:global-config:db-config:logic-delete-field: flag # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)logic-delete-value: 1 # 逻辑已删除值(默认为 1)logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
3.实体类中指定逻辑删除字段:
@TableLogic
private Integer deleted;
4.测试
@Testpublic void deletedTest(){userService.removeById(1);}
5.实际执行的语句
UPDATE bookstore.user SET deleted=1 WHERE id=? AND deleted=0
6.加上逻辑删除后执行查找:
@Testpublic void select(){User user = userService.getById(1);System.out.println(user);}
此时执行的sql:
SELECT id,name,age,email,version,deleted FROM bookstore.user WHERE id=? AND deleted=0
3.自动填充功能
实现数据库表的更新有记录:gmt_create,gmt_modified
方式一:基于数据库表
创建时间不需要勾选根据时间戳更新:
效果:
执行更新操作后:
方式二:代码中设置
表中创建两个字段:
实体类注解填充字段:
@TableField(fill = FieldFill.INSERT)private Date cmtCreate;@TableField(fill = FieldFill.INSERT_UPDATE)private Date cmtModified;
自定义实现类MyMetaObjectHandler:
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {log.info("start insert fill ....");this.setFieldValByName("cmtCreate", new Date(), metaObject);this.setFieldValByName("cmtModified", new Date(), metaObject);}@Overridepublic void updateFill(MetaObject metaObject) {log.info("start update fill ....");this.setFieldValByName("cmtModified", new Date(), metaObject);}
}
更新操作后:
4.日志分析
mybatis-plus:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
MyBatis-Plus 学习笔记相关推荐
- mybatis框架--学习笔记(下)
上篇:mybatis框架--学习笔记(上):https://blog.csdn.net/a745233700/article/details/81034021 8.高级映射: (1)一对一查询: ①使 ...
- mybatis框架--学习笔记(上)
使用JDBC操作数据库的问题总结: (1)数据库连接,使用时创建,不使用时立即释放,对数据库进行频繁连接开启和关闭,造成数据库资源浪费,影响数据库性能. 设想:使用数据库连接池管理数据库连接. (2) ...
- [Spring+SpringMVC+Mybatis]框架学习笔记(四):Spring实现AOP
上一章:[Spring+SpringMVC+Mybatis]框架学习笔记(三):Spring实现JDBC 下一章:[Spring+SpringMVC+Mybatis]框架学习笔记(五):SpringA ...
- 2021年3月8日:MyBatis框架学习笔记02:利用MyBatis实现CRUD操作
MyBatis框架学习笔记02:利用MyBatis实现CRUD操作 在第一节课中我们在UserMapper.xml里定义了两个查询语句:findById和findAll,对应的在UserMapper接 ...
- 【Mybatis】学习笔记01:连接数据库,实现增删改
需要数据库SQL的请跳转到文末 哔哩哔哩 萌狼蓝天[转载资料][尚硅谷][MyBatis]2022版Mybatis配套MD文档[Mybatis]学习笔记01:连接数据库,实现增删改[Mybatis]学 ...
- MyBatis框架学习笔记(3)——B站动力节点
文章目录 (0)介绍 (1)返回主键的标签 (2)UUID的概念 (3)update时< set >标签的使用 (4)表与表的关联关系 一对多关联 多对一关联 一对一关联 多对多关联 (5 ...
- Mybatis的学习笔记
MyBatis Mybatis是一款非常优秀的持久层框架,学习的目的是要掌握精通. 那么今天我们就来学习一下这个优秀的框架知识! 此外,由于博主的水平的原因,文章的质量可能不会太高,请酌情观看.如果大 ...
- 【自用】Mybatis的学习笔记(第一天)
捋一下啊 记录一下我总结的经验 我的笔记记录的层次很烂 所以我要在xmind上把层次记录下来 然后按着xmind 层次去敲代码 哪里出了问题,直接去ctrl+f 好了,他妈的开始学习了 ORM 框架 ...
- 1 (SSM) springMVC + spring + Mybatis(MySQL)学习笔记 ------ 阶段成果笔记
学习了一段时间spring,springMVC和Mybatis,从开始学到现在熬了好多夜晚,好几个深夜和bug作战,真是难受. 打算写系列学习笔记,第一篇从一个小的成果说起吧,刚刚学的看这篇可能有点吃 ...
- Mybatis 3学习笔记(一)
主要内容: What is MyBatis? Why MyBatis? Installing and configuring MyBatis Sample domain model What is M ...
最新文章
- mysql中取出的时间日期多个.0
- yum 安装指定版本php,怎样通过yum安装指定版本的php
- Python初探---2x版本与3x版本的区别
- .net 内嵌 GeckoWebBrowser (firefox) 核心浏览器
- QTP、LoadRunner、QC工具下载地址
- 滤波器开发之五:基于算术平均的限幅滤波器
- 记事本可以编辑html语言吗,笔记本win7系统使用记事本编辑和运行html代码的方法...
- 如何在Windows 10中启用关闭事件跟踪程序
- 华为交换机通用配置方式方法
- RNA 6. 差异基因表达之-- 火山图 (volcano)
- c语言三角形的周长和面积公式,计算三角形的周长和面积
- win11安装Pandoc
- Leetcode1278
- linux 服务器 安装网卡驱动,Linux系统下安装Intel千兆网卡驱动
- 微信小程序开发之——仿微信视频录制上传
- tf15: 中文语音识别
- 3dMax教程网站 文字版
- 行人重识别(21)——行人重识别算法性能指标
- MAC m1芯片,下载安装natapp
- SAP连接电脑串口读数(电子称,磅等数据读取)
热门文章
- CentOS:linux开放指定端口命令
- Python中的json.dumps()和json.loads()函数
- jsp ---- JSTL
- 微型计算机字长为4表示,一台微型计算机的字长为4个字节,它表示什么?
- springcloud五大组件?注解_spring cloud实现简单的微服务架构
- @Component注解的用法
- ActiveMQ 认证
- oracle删除数据释放表空间流程
- mysql 读取oracle_RobotFramework读取mysql和oracle数据库
- 如何转换并压缩png格式图片