Mybatis-plus常用API全套教程,看完没有不懂的
点击关注公众号,Java干货及时送达
作者:java架构师阿松
www.toutiao.com/i6869621037831717387
前言
官网:
https://baomidou.com/
创建数据库
数据库名为mybatis_plus
创建表
创建user表
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)
);
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');
注意:-- 真实开发中往往都会有这四个字段,version(乐观锁)、deleted(逻辑删除)、gmt_create(创建时间)、gmt_modified(修改时间)
初始化项目
使用SpringBoot器 初始化!
导入依赖
<!-- 数据库驱动 -->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- lombok -->
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId>
</dependency>
<!-- mybatis-plus -->
<!-- mybatis-plus 是自己开发,并非官方的! -->
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.0.5</version>
</dependency>
注意:尽量不要同时导入 mybatis 和 mybatis-plus!避免版本的差异造成无法预知的问题。
连接数据库
创建application.yml
spring:profiles:active: devdatasource:
# 驱动不同 mysql 5 com.mysql.jdbc.Driver
# mysql 8 com.mysql.cj.jdbc.Driver、需要增加时区的配置serverTimezone=GMT%2B8url: jdbc:mysql://localhost:3306/mybatis_plus?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8driver-class-name: com.mysql.cj.jdbc.Driverusername: rootpassword: root
业务代码
实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {private Long id;private String name;private Integer age;private String email;
}
mapper接口
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.kuang.pojo.User;
import org.springframework.stereotype.Repository;
// 在对应的Mapper上面继承基本的类 BaseMapper
@Repository // 代表持久层
public interface UserMapper extends BaseMapper<User> {// 所有的CRUD操作都已经编写完成了
}
注意点,我们需要在主启动类上去扫描我们的mapper包下的所有接口 @MapperScan(“com.kwhua.mapper”)
测试
@SpringBootTest
class MybatisPlusApplicationTests {// 继承了BaseMapper,所有的方法都来自己父类// 我们也可以编写自己的扩展方法!@Autowiredprivate UserMapper userMapper;@Testvoid contextLoads() {// 参数是一个 Wrapper ,条件构造器,这里我们先设置条件为空,查询所有。List<User> users = userMapper.selectList(null);users.forEach(System.out::println);}
}
所有数据输出
配置日志
我们所有的sql现在是不可见的,我们希望知道它是怎么执行的,所有我们要配置日志的输出 application.yml文件添加日志配置
#配置日志
mybatis-plus:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
查看执行sql的日志信息
三.Mybatis-plus的CRUD
插入操作
// 测试插入@Testpublic void testInsert(){User user = new User();user.setName("kwhua_mybatis-plus_insertTest");user.setAge(15);user.setEmail("310697723@qq.com");int result = userMapper.insert(user); // 帮我们自动生成idSystem.out.println(result); // 受影响的行数System.out.println(user); // 看到id会自动填充。 }
看到id会自动填充。数据库插入的id的默认值为:全局的唯一id
主键生成策略
1)主键自增 1、实体类字段上 @TableId(type = IdType.AUTO)
2、数据库id字段设置为自增!3、再次测试(可以看到id值比上次插入的大1)id的生成策略源码解释
public enum IdType {AUTO(0), // 数据库id自增NONE(1), // 未设置主键INPUT(2), // 手动输入ID_WORKER(3), // 默认的方式,全局唯一idUUID(4), // 全局唯一id uuidID_WORKER_STR(5); //ID_WORKER 字符串表示法
}
以上不再逐一测试。
更新操作
@Testpublic void testUpdate(){User user = new User();// 通过条件自动拼接动态sqluser.setId(1302223874217295874L);user.setName("kwhua_mybatis-plus_updateTest");user.setAge(20);// 注意:updateById 但是参数是一个对象!int i = userMapper.updateById(user);System.out.println(i);}
自动填充
创建时间、修改时间!这两个字段操作都是自动化完成的,我们不希望手动更新!阿里巴巴开发手册:所有的数据库表都要配置上gmt_create、gmt_modified!而且需要自动化!
方式一:数据库级别(工作中一般不用)
1、在表中新增字段 gmt_create, gmt_modified
2、把实体类同步
private Date gmtCreate;
private Date gmtModified;
3、再次查看
方式二:代码级别 1、删除数据库的默认值、更新操作!
2、实体类字段属性上需要增加注解
// 字段添加填充内容@TableField(fill = FieldFill.INSERT)private Date gmt_create;@TableField(fill = FieldFill.INSERT_UPDATE)private Date gmt_modified;
3、编写处理器来处理这个注解即可!
@Slf4j
@Component // 一定不要忘记把处理器加到IOC容器中!
public class MyMetaObjectHandler implements MetaObjectHandler {// 插入时的填充策略@Overridepublic void insertFill(MetaObject metaObject) {log.info("start insert fill.....");// setFieldValByName(String fieldName, Object fieldVal, MetaObject metaObjectthis.setFieldValByName("gmt_create",new Date(),metaObject);this.setFieldValByName("gmt_modified",new Date(),metaObject);}// 更新时的填充策略@Overridepublic void updateFill(MetaObject metaObject) {log.info("start update fill.....");this.setFieldValByName("gmt_modified",new Date(),metaObject);}
}
4、测试插入和更新,检查时间变化。
乐观锁
乐观锁 : 顾名思义,十分乐观,它总是认为不会出现问题,无论干什么不去上锁!如果出现了问题, 再次更新值测试 悲观锁:顾名思义,十分悲观,它总是认为总是出现问题,无论干什么都会上锁!再去操作!
乐观锁实现方式:
取出记录时,获取当前version 更新时,带上这个version 执行更新时, set version = newVersion where version = oldVersion 如果version不对,就更新失败
乐观锁:1、先查询,获得版本号 version = 1
-- A
update user set name = "kwhua", version = version + 1
where id = 2 and version = 1
-- B 线程抢先完成,这个时候 version = 2,会导致 A 修改失败!
update user set name = "kwhua", version = version + 1
where id = 2 and version = 1
乐观锁测试
1、给数据库中增加version字段!
2、实体类加对应的字段
@Version //乐观锁Version注解private Integer version;
3、注册组件
// 扫描我们的 mapper 文件夹
@MapperScan("com.kwhua.mapper")
@EnableTransactionManagement
@Configuration // 配置类
public class MyBatisPlusConfig {// 注册乐观锁插件@Beanpublic OptimisticLockerInterceptor optimisticLockerInterceptor() {return new OptimisticLockerInterceptor();}}
4、测试
// 测试乐观锁成功!@Testpublic void testOptimisticLocker(){// 1、查询用户信息User user = userMapper.selectById(1L);// 2、修改用户信息user.setName("kwhua");user.setEmail("123456@qq.com");// 3、执行更新操作userMapper.updateById(user);}
version字段已经由1变成了2
// 测试乐观锁失败!多线程下@Testpublic void testOptimisticLocker2(){// 线程 1User user = userMapper.selectById(1L);user.setName("kwhua111");user.setEmail("123456@qq.com");// 模拟另外一个线程执行了插队操作User user2 = userMapper.selectById(1L);user2.setName("kwhua222");user2.setEmail("123456@qq.com");userMapper.updateById(user2);// 自旋锁来多次尝试提交!userMapper.updateById(user); // 如果没有乐观锁就会覆盖插队线程的值!}
可以看到线程1执行更新失败
查询操作
// 测试查询@Testpublic void testSelectById(){User user = userMapper.selectById(1L);System.out.println(user);}// 测试批量查询!@Testpublic void testSelectByBatchId(){List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));users.forEach(System.out::println);}// 按条件查询之一使用map操作@Testpublic void testSelectByBatchIds(){HashMap<String, Object> map = new HashMap<>();// 自定义要查询map.put("name","kwhua");map.put("age",15);List<User> users = userMapper.selectByMap(map);users.forEach(System.out::println);}
1、配置拦截器组件
// 分页插件
@Bean
public PaginationInterceptor paginationInterceptor() {return new PaginationInterceptor();
}
2、直接使用Page对象即可!
// 测试分页查询
@Test
public void testPage(){// 参数一:当前页// 参数二:页面大小Page<User> page = new Page<>(2,5);userMapper.selectPage(page,null);page.getRecords().forEach(System.out::println);System.out.println(page.getTotal());
}
物理删除
// 测试删除@Testpublic void testDeleteById(){userMapper.deleteById(1L);}// 通过id批量删除@Testpublic void testDeleteBatchId(){userMapper.deleteBatchIds(Arrays.asList(2L,3L));}// 通过map删除@Testpublic void testDeleteMap(){HashMap<String, Object> map = new HashMap<>();map.put("name","kwhua");userMapper.deleteByMap(map);}
逻辑删除
物理删除 :从数据库中直接移除 逻辑删除 :在数据库中没有被移除,而是通过一个变量来让它失效!deleted = 0 => deleted = 1 管理员可以查看被删除的记录!防止数据的丢失,类似于回收站!
1、在数据表中增加一个 deleted 字段2、实体类中增加属性
@TableLogic //逻辑删除private Integer deleted;
3、配置
// 逻辑删除组件!@Beanpublic ISqlInjector sqlInjector() {return new LogicSqlInjector();}
配置文件配置
global-config:db-config:logic-delete-value: 1logic-not-delete-value: 0
4、测试 测试删除
字段值也从0修改成了1测试查询
性能分析插件
作用:性能分析拦截器,用于输出每条 SQL 语句及其执行时间 MP也提供性能分析插件,如果超过这个时间就停止运行!1、导入插件
/*** SQL执行效率插件*/@Bean@Profile({"dev","test"})// 设置 dev test 环境开启,保证我们的效率public PerformanceInterceptor performanceInterceptor() {PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();performanceInterceptor.setMaxTime(100); //ms 设置sql执行的最大时间,如果超过了则不执行performanceInterceptor.setFormat(true);return performanceInterceptor;}
条件构造器(Wrapper)
isNotNull .gt
@Testvoid contextLoads() {// 查询name不为空的用户,并且邮箱不为空的用户,年龄大于等于12QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.isNotNull("name") //不为空.isNotNull("email").ge("age",18);userMapper.selectList(wrapper).forEach(System.out::println); // 和我们刚才学习的map对比一下}
.eq
@Testvoid test2(){// 查询名字kwhuaQueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.eq("name","kwhua");User user = userMapper.selectOne(wrapper); // 查询一个数据用selectOne,查询多个结果使用List 或者 MapSystem.out.println(user);}
其他方法可以自己测试...
代码自动生成器
// 代码自动生成器
public class generateCode {public static void main(String[] args) {// 需要构建一个 代码自动生成器 对象AutoGenerator mpg = new AutoGenerator();// 配置策略// 1、全局配置GlobalConfig gc = new GlobalConfig();String projectPath = System.getProperty("user.dir");gc.setOutputDir(projectPath+"/src/main/java");gc.setAuthor("kwhua");//作者名称gc.setOpen(false);gc.setFileOverride(false); // 是否覆盖gc.setIdType(IdType.ID_WORKER);gc.setDateType(DateType.ONLY_DATE);gc.setSwagger2(true);//实体属性 Swagger2 注解// 自定义文件命名,注意 %s 会自动填充表实体属性!gc.setServiceName("%sService"); gc.setControllerName("%sController");gc.setServiceName("%sService");gc.setServiceImplName("%sServiceImpl");gc.setMapperName("%sMapper");gc.setXmlName("%sMapper");mpg.setGlobalConfig(gc);//2、设置数据源DataSourceConfig dsc = new DataSourceConfig();dsc.setUrl("jdbc:mysql://localhost:3306/kwhua_test?
useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8");dsc.setDriverName("com.mysql.cj.jdbc.Driver");// dsc.setDriverName("com.mysql.jdbc.Driver"); //mysql5.6以下的驱动dsc.setUsername("root");dsc.setPassword("root");dsc.setDbType(DbType.MYSQL);mpg.setDataSource(dsc);//3、包的配置PackageConfig pc = new PackageConfig();pc.setParent("com.kwhua"); //包名pc.setModuleName("model"); //模块名pc.setEntity("entity");pc.setMapper("mapper");pc.setService("service");pc.setController("controller");mpg.setPackageInfo(pc);//4、策略配置StrategyConfig strategy = new StrategyConfig();strategy.setInclude("user","course"); // 设置要映射的表名strategy.setNaming(NamingStrategy.underline_to_camel);strategy.setColumnNaming(NamingStrategy.underline_to_camel);strategy.setEntityLombokModel(true); // 自动lombok;strategy.setLogicDeleteFieldName("deleted");// 自动填充配置TableFill gmtCreate = new TableFill("gmt_create", FieldFill.INSERT);TableFill gmtModified = new TableFill("gmt_modified",FieldFill.INSERT_UPDATE);ArrayList<TableFill> tableFills = new ArrayList<>();tableFills.add(gmtCreate);tableFills.add(gmtModified);strategy.setTableFillList(tableFills);// 乐观锁strategy.setVersionFieldName("version");//根据你的表名来建对应的类名,如果你的表名没有下划线,比如test,那么你就可以取消这一步strategy.setTablePrefix("t_");strategy.setRestControllerStyle(true); //rest请求//自动转下划线,比如localhost:8080/hello_id_2strategy.setControllerMappingHyphenStyle(true); mpg.setStrategy(strategy);mpg.execute(); //执行}
}
执行主方法即可生成对应代码
热门内容:史上最强Redis6.0,世界排名第一!为什么不推荐使用BeanUtils属性转换工具
Redis分布式锁使用不当,酿成一个重大事故,超卖了100瓶飞天茅台!!!
常用正则表达式最强整理(速查手册)
最近面试BAT,整理一份面试资料《Java面试BAT通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。
明天见(。・ω・。)ノ♡
Mybatis-plus常用API全套教程,看完没有不懂的相关推荐
- mybatis plus 日志打印_Mybatis-plus常用API全套教程,看完没有不懂的
★★★建议星标我们★★★ Java进阶架构师★"星标"!这样才不会错过每日进阶架构文章呀. 2020年Java原创面试题库连载中 [000期]Java最全面试题库思维导图 [020 ...
- Java技术:Mybatis-plus常用API全套教程,值得收藏!
前言 官网: https://baomidou.com/ 创建数据库 数据库名为mybatis_plus 创建表 创建user表 DROP TABLE IF EXISTS user; CREATE T ...
- 千言万语汇总的Mybatis-plus常用API全套教程
前言 官网: https://baomidou.com/ 创建数据库 数据库名为mybatis_plus 创建表 创建user表 DROP TABLE IF EXISTS user; CREATE T ...
- Mybatis-plus常用API全套教程
前言 前两天,我收到了蚂蚁金服的offer,从朋友的内推开始面试到拿到最后offer经历了4面技术.一面交叉面和一面HR面.经过了漫长的等待和几次几乎折磨的面试之后,终于拿到了offer. 正文 下文 ...
- 面试挂在JVM?别慌,图文讲解JVM工作原理,看完还不懂我跪键盘
本文转载自:面试挂在JVM?别慌,图文讲解JVM工作原理,看完还不懂我跪键盘 JDK,JRE,JVM的联系是啥? JVM Java Virtual Machine JDK Java Developme ...
- 你不知道的js中关于this绑定机制的解析[看完还不懂算我输]
前言 最近正在看<你不知道的JavaScript>,里面关于this绑定机制的部分讲的特别好,很清晰,这部分对我们js的使用也是相当关键的,并且这也是一个面试的高频考点,所以整理一篇文章分 ...
- Android进阶必备:滑动冲突解决与事件分发机制(附视频讲解)这篇看完还不懂请寄刀片
1.前言 Android学习一段时间,需求做多了必然会遇到滑动冲突问题,比如在一个ScrollView中要嵌套一个地图View,这时候触摸移动地图或者放大缩小地图就会变得不太准确甚至没有反应,这就是遇 ...
- 什么是API?(看完你就理解了)
阅读编程资料时经常会看到API这个名词,网上各种高大上的解释估计放倒了一批初学者.初学者看到下面这一段话可能就有点头痛了. API(Application Programming Interface, ...
- java中什么方法用来清空流_这个真的写的很细,JavaIO中的常用处理流,看完只有10%的人还不懂了...
JavaIO中的常用处理流 在前面,我们了解了有关JavaIO流基础的使用,其中对于IO流来说最基础的四大基类就是InputStream.OutputStream.Reader.Writer.而我们对 ...
最新文章
- python字符串格式化之学习笔记
- 机器学习Python实践》——数据导入(CSV)
- 如何在Bash脚本中将DOS / Windows换行符(CRLF)转换为Unix换行符(LF)?
- python爬虫案例-Python爬取租房数据实例,据说可以入门爬虫的小案例!
- matlab 正在等待响应标头。可能服务器没有响应,或者 weboptions.Timeout,Expect:100-continue
- 操作系统中的同步和异步
- java表数据去重_java8实现列表去重,java8的stream 和lambda的使用实例
- AI超人赛车手狂虐人类登Nature封面!1000台PS4训练,「苏菲」极限超车独霸赛道...
- CSS——FC(BFC/IFC/FFC/GFC)超详细版+原理案例分析
- ifconfig 命令,改变主机名,改DNS hosts、关闭selinux firewalld netfilter 、防火墙iptables规则...
- ThinkPHP视图模型实例
- 超详细 excel 基础知识
- FPGA在图像处理中的应用
- 目标检测之YOLOv5算法分析
- STATA 学习笔记: outlier(离群值)的处理
- 电商项目:高仿小米商城(API文档)
- MySQL查询之内存临时表
- Spectrum数据采集卡和任意波形发生器在杨百翰大学声波研究中的应用
- 四川锦城学院计算机专业好不,四川大学锦城学院计算机专业如何?
- c/c++: window下安装mingw-w64
热门文章
- 贪心 POJ - 3617 ​​​​​​​Best Cow Line
- 暑期集训2:ACM基础算法 练习题C:CF-1008A
- 谜题59:什么是差?
- SPOJ ATOMS - Atoms in the Lab
- Oracle Sales Cloud 实施(二)
- atitit.跨架构 bs cs解决方案. 自定义web服务器的实现方案 java .net jetty HttpListener...
- 《代码大全2》读后感czz
- PHP:isset()-检测变量是否被设置
- fieldset 使用小案例
- sharepoint自带JS函数获取URL参数