mybatis_plus使用教程

mybatis_plus是mybatis的升级版,类似于JPA,可以很方便很高效的完成日常开发。为简化开发提高效率而生。

官网:https://mp.baomidou.com/

目录

一. MP的简单搭建

1. 引入依赖:基于springboot

2. 创建springJDBC连接:

3. springboot启动类添加扫描注解,扫描mapper接口

4.简单实用快速入门

5. 配置日志

二. CRUD

1. insert

1.1 ID生成策略

2. update更新操作

2.1 普通的更新操作

2.2 数据库时间字段的自动填充

2.3 乐观锁

3. select查询操作

3.1 查询

3.2 分页查询

4. 删除操作

4.1 逻辑删除

三. 插件

1. SQL性能分析插件

四. wrapper条件构造器

4.1 wrapper

五. 自动生成代码

六. MP通过XML文件执行sql示例





一. MP的简单搭建

1. 引入依赖:基于springboot

<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.3.2</version> </dependency> #3.0.3是比较老的版本,自带了gen等相关.3.3.2则需要另外引入

2. 创建springJDBC连接:

spring: datasource: username: root password: root #对于mysql8.0的版本,必须声明时区,此处声明的时区为上海时区,并且加载类是: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/mybatis?useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai driver-class-name: com.mysql.cj.jdbc.Driver

3. springboot启动类添加扫描注解,扫描mapper接口

@MapperScan("com.kuang.mybatis_plus.mapper")

4.简单实用快速入门

按照官网的实例。创建User表,创建user实体类,创建userMapper接口,完成MP的简单使用。

#userMapper接口,继承了baseMapper(MP中mapper接口的父类,包装了常用的CRUD) public interface UserMapper extends BaseMapper<User> { } #测试: @Autowired private UserMapper userMapper; @Test void contextLoads() { List<User> users = userMapper.selectList(null); users.forEach(u -> System.out.println(u.getName())); //完成了user表的无条件查询 }

通过以上步骤,即可完成User的CRUD,不需要编写XML文件,也不需要写SQL,baseMapper已经帮我们包装好了。同时,如果MP包装好的方法不能满足我们的业务查询,则可以通过正常的使用mybatis通过自定义SQL即可完成。MP就是mybatis+JPA的整合方式。

5. 配置日志

MP中所有的SQL都是不可见的,我们希望知道他们是怎么执行的,所以需要配置日期,开发的时候把日期打开,知道是怎么执行的,也可以把执行慢的SQL揪出来,上线后,把日志关掉,因为日志是有损耗性能的。

在配置文件中添加日志,在执行SQL时,具体的执行SQL语句就会被打印出来了。

二. CRUD

1. insert

通过baseMapper的包装方法insert完成插入

执行代码:

 @Test public void testInsert() { User user = new User(); user.setName("插入"); user.setAge(18); user.setEmail("123@qq.com"); //user的ID自动生成了,MP会根据一定的策略完成ID的生成 int result = userMapper.insert(user); System.out.println("影响的条数:" + result); }

测试结果:

1.1 ID生成策略

此处实例中生成的ID是一串LONG类型的数字ID,是通过雪花算法自动生成的唯一ID。

关于ID的生成博客可以参考:https://www.cnblogs.com/haoxinyue/p/5208136.html

雪花算法:snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0。

如何设置主键生成策略呢?

在实体类User中,MP提供了注解@TableId来完成主键策略的设置

type就是策略的类型,IdType是MP提供的策略枚举,我们可以根据具体的业务场景,选择不同的ID生成策略。分析如下:

public enum IdType { AUTO(0), //自增策略,如果注解type为AUTO,则需要数据库主键字段也为自增,否则会报错 NONE(1), // 没有策略,代表MP不设置任何策略,适用于没有主键的表 INPUT(2), // 手动输入,需要插入时,手动对实体设置ID值 ID_WORKER(3),//默认的策略,也就是我们的雪花算法LONG类型 UUID(4), //生成唯一的UUID值 ID_WORKER_STR(5); //生成雪花算法的字符创类型值 }

2. update更新操作

2.1 普通的更新操作

 @Test public void testUpdate() { User user = new User(); user.setId(5L); user.setName("这个是一个被修改的name"); user.setEmail("test5@baomidou.com"); //updateById的参数是一个对象,并且需要设置ID,MP就会自动根据user对象完成更新。set什么值,就会去更新什么值。不set就不会更新。 int i = userMapper.updateById(user); System.out.println(i); }

2.2 数据库时间字段的自动填充

对于系统中,create_time update_time几乎是必不可少的字段,对于这两个字段,不能每次都去set值。可以通过两种方式完成自动填充。

①数据库层面(不建议使用):update_time设置默认值为CURRENT_TIMESTAMP,也就是当前时间,并勾选自动更新

create_time直接设置默认值为CURRENT_TIMESTAMP即可。不需要勾选自动更新。即可完成自动填充。

②代码层面:

MP的官网介绍了自动填充功能,手动编写实现以下:

在User实体类中,添加注解

@TableField(fill = FieldFill.INSERT),标明哪个字段需要自动填充,并通过fill设置自动填充策略。

然后编写处理器,来处理标识了该注解字段的自动填充

package com.mybatis_plus.handler; import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; import org.apache.ibatis.reflection.MetaObject; import java.util.Date; /** * @author hengtao.wu * MP自动填充处理器实现 * @Date 2020/7/9 14:00 **/ public class MyMetaObjectHandler implements MetaObjectHandler { @Override public void insertFill(MetaObject metaObject) { //执行插入操作时,被注解@TableField(fill = FieldFill.INSERT)、@TableField(fill = FieldFill.INSERT_UPDATE)标记的字段会被自动填充。 this.setFieldValByName("createTime", new Date(), metaObject); this.setFieldValByName("updateTime", new Date(), metaObject); //新方法 3.3.0版本后 // this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本 3.3.0(推荐使用) // this.fillStrategy(metaObject, "createTime", LocalDateTime.now()); // 也可以使用(3.3.0 该方法有bug请升级到之后的版本如`3.3.1.8-SNAPSHOT`) // 上面选其一使用 } @Override public void updateFill(MetaObject metaObject) { //执行更新操作时,被注解@TableField(fill = FieldFill.UPDATE)、@TableField(fill = FieldFill.INSERT_UPDATE)标记的字段会被自动填充。 this.setFieldValByName("updateTime", new Date(), metaObject); //新版本方法:3.3.0以后 // this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本 3.3.0(推荐使用) // this.fillStrategy(metaObject, "updateTime", LocalDateTime.now()); // 也可以使用(3.3.0 该方法有bug请升级到之后的版本如`3.3.1.8-SNAPSHOT`) // 上面选其一使用 } }

2.3 乐观锁

乐观锁:认为什么事情都是乐观的一定能成功的,通过一个version版本号来完成控制,获取时的版本号要跟执行更新时库中的版本号要一直,否则就会执行失败。

MP提供了支持乐观锁的注解@Version,可以通该注解自动完成拦截并验证乐观锁的操作。使用过程如下:

①首先在User表中添加version字段,实体类中添加属性version,并在该属性值上添加注解@Version

@Version //添加乐观锁控制 private Integer version;

②编写配置类,完成spring的IOC容器中注册乐观锁插件

/** * @author hengtao.wu * MP的乐观锁插件,在执行@Version注解时,会拦截操作,并执行判断乐观锁的SQL。 * @Date 2020/7/9 14:26 **/ @Configuration public class MybatisPlusConfig { @Bean public OptimisticLockerInterceptor optimisticLockerInterceptor() { return new OptimisticLockerInterceptor(); } }

此时,被@Version注解标注的属性,就会执行乐观锁的更新策略机制。

3. select查询操作

3.1 查询

通过MP的包装方法,可以满足大多数的查询。

/** * 通过ID查询 */ @Test public void testSelectById() { User user = userMapper.selectById(1L); System.out.println(user); } /** * 通过多个ID集合查询 */ @Test public void testSelectBatchId() { List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3)); users.forEach(System.out::println); } /** * 通过拼接where条件查询 */ @Test public void testSelectByMap() { HashMap<String, Object> map = new HashMap<>(); map.put("user_name", "插入"); List<User> users = userMapper.selectByMap(map); users.forEach(System.out::println); }

3.2 分页查询

MP自己封装了Page对象,用来完成分页操作,但是使用之前还是需要注册分页拦截器。

能够实现按照pageSize和pageNo进行分页,并且可以设置排序字段和方式:

 @Test public void testPage() { Page<User> page = new Page<>(1,5); //设置排序方式可以通过一下两种均可: // page.setAsc("version", "age");ag // page.setAscs(Arrays.asList("version", "age")); //一下排序方式为,ORDER BY age DESC, version ASC page.setDesc("age"); page.setAsc("version"); userMapper.selectPage(page, null); page.getRecords().forEach(System.out::println); page.getTotal(); //获取查询结果总条数 page.getSize(); // 本次分页查询的总数(本页条数) page.getCurrent(); //当前所在分页数 System.out.println("OK"); }

4. 删除操作

/** * 通过ID删除 */ @Test public void testDelById() { userMapper.deleteById(1281072207564996609L); } /** * 通过多个ID删除 */ @Test public void testDelBatchId() { userMapper.deleteBatchIds(Arrays.asList(1281068592024592385L, 1L)); } /** * 通过map条件删除,map条件中是精确删除,不能满足模糊条件 */ @Test public void testDelMap() { HashMap<String, Object> map = new HashMap<>(); map.put("age", 20); userMapper.deleteByMap(map); }

4.1 逻辑删除

我们在业务操作中,通过会使用一个is_delete来控制逻辑删除。MP则提供了这样的注解,帮助我们完成逻辑删除和查询

1. 在is_delete属性上添加注解

@TableLogic

2. 完成注册类bean(3.1.1之后,不再需要这一步了)

/** *注册逻辑删除组件 */ @Bean public ISqlInjector sqlInjector() { return new LogicSqlInjector(); }

3. 在配置文件中声明 逻辑删除的删除与未删除值

mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl global-config: db-config: #logic-delete-field: flag # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2) logic-delete-value: 1 #删除是1 logic-not-delete-value: 0 #未删除是0

4. 此时,通过mapper的delete方法,则就是逻辑删除了,查询更新等操作,也都是自动拼接sql where is_delete=0

如果确实需要手动删除,则手写SQL完成物理删除即可。

三. 插件

1. SQL性能分析插件

3.0.3的使用方式,后面高版本的使用方式可以自行查询

@Bean @Profile({"dev", "test"}) //表示在dev和test环境才会启动该性能分析插件 public PerformanceInterceptor performanceInterceptor() { PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor(); //设置SQL执行时间的最大毫秒数,如果超过该毫秒数,则会跑出异常,执行失败 performanceInterceptor.setMaxTime(100); //设置SQL是否格式化(美化sql) performanceInterceptor.setFormat(true); return performanceInterceptor; } 

所有的查询都会被监控,并输出格式化SQL语句。

四. wrapper条件构造器

4.1 wrapper

通过条件构造器完成复杂的查询sql,通过注入的方式完成

官网提供了如下的方法可以进行查阅

使用示例:(更多的使用测试,请移步官网提供的方法完成使用)

@Test public void test1() { //查询一个version>=1, 并且age在10-50岁之间的SQL QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.ge("version", 1) .between("age", 10 ,50); List<User> users = userMapper.selectList(wrapper); } /** * SELECT * id, * user_name, * age, * email, * version, * is_delete * FROM * user * WHERE * is_delete=0 * AND id IN ( * select * id * from * user * where * id >= 3 * ) */ @Test public void test2() { //查询一个id在子查询结果中的SQL QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.inSql("id", "select id from user where id >= 3"); List<User> users = userMapper.selectList(wrapper); users.forEach(System.out::println); }

五. 自动生成代码

MP可以提供大量的自定义参数,完成mapper/xml/service/pojo/controller代码的自动生成。简单使用如下:

导入依赖:

<dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity-engine-core</artifactId> <version>2.0</version> </dependency>
package com.kuang.mybatis_plus; import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.generator.AutoGenerator; import com.baomidou.mybatisplus.generator.config.DataSourceConfig; import com.baomidou.mybatisplus.generator.config.GlobalConfig; import com.baomidou.mybatisplus.generator.config.PackageConfig; import com.baomidou.mybatisplus.generator.config.StrategyConfig; import com.baomidou.mybatisplus.generator.config.rules.DateType; import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy; /** * @author hengtao.wu * @Date 2020/7/9 10:11 **/ public class gen { // 创建一个 代码自动生成器对象 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("hengtao.wu"); //设置作者注解 gc.setOpen(false); //是否打开资源管理器 gc.setFileOverride(false); //是否覆盖原来生成的 gc.setServiceName("%sService"); //去service的I前缀 gc.setIdType(IdType.ID_WORKER); //设置全局的ID生成策略。 gc.setDateType(DateType.ONLY_DATE); //设置全局的时间类型 gc.setSwagger2(false); //设置是否开启swagger mpg.setGlobalConfig(gc); //2. 设置数据源,自动生成代码会根据该配置查找数据表 DataSourceConfig dsc = new DataSourceConfig(); dsc.setUrl("jdbc:mysql://localhost:3306/mybatis?useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai"); dsc.setUsername("root"); dsc.setPassword("root"); dsc.setDriverName("com.mysql.cj.jdbc.Driver"); dsc.setDbType(DbType.MYSQL); mpg.setDataSource(dsc); //3. 包的配置 PackageConfig pc = new PackageConfig(); // pc.setModuleName("mybatis"); //设置模块,也就是跟路径下,是否创建一个模块的文件夹,多用于多数据源和库的情况 pc.setParent("com.kuang.mybatis_plus"); //设置跟路径 pc.setEntity("pojo"); //设置实体类的包名 pc.setMapper("mapper"); //设置mapper的包名 xml文件也会在该路径下 pc.setService("service"); //设置service的包名 pc.setController("controller"); //设置controller的包名 mpg.setPackageInfo(pc); //4. 策略配置 StrategyConfig sc = new StrategyConfig(); sc.setInclude("user"); //设置要映射生成的表名,可以是多个 sc.setNaming(NamingStrategy.underline_to_camel); //设置名称为下划线转大写的驼峰写法 sc.setColumnNaming(NamingStrategy.underline_to_camel); //设置字段的也是驼峰写法 sc.setEntityLombokModel(true); //自动设置lombok注解 sc.setLogicDeleteFieldName("is_delete"); //设置逻辑删除字段名 sc.setVersionFieldName("version"); //设置乐观锁机制 // 设置自动填充字段,例如更新时间、创建时间 /* TableFill createTime = new TableFill("create_time", FieldFill.INSERT); TableFill updateTime = new TableFill("update_time", FieldFill.INSERT_UPDATE); ArrayList<TableFill> list = new ArrayList<>(); list.add(createTime); list.add(updateTime); sc.setTableFillList(list);*/ sc.setRestControllerStyle(true); //是否开启restful风格的controller sc.setControllerMappingHyphenStyle(true); //是否开启下划线的URL mpg.setStrategy(sc); mpg.execute(); //执行生成 } } 

六. MP通过XML文件执行sql示例

①配置xml文件的映射路径以及PO的包所在路径

mybatis-plus:

mapper-locations: classpath:xml/*.xml

type-aliases-package: com.kuang.mybatis_plus.po

②创建XML文件,并设置namespace映射到对应的mapper接口:

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.kuang.mybatis_plus.mapper.UserMapper"> <!-- 可根据自己的需求,是否要使用,如果配置了映射实体包,此处的resultType可以直接写类名 --> <!--<resultMap type="com.kuang.mybatis_plus.po.User" id="user"> <id column="id" property="id" jdbcType="BIGINT" /> <result column="user_name" property="userName" jdbcType="VARCHAR" /> <result column="age" property="age" jdbcType="INTEGER" /> <result column="email" property="email" jdbcType="VARCHAR" /> <result column="version" property="version" jdbcType="INTEGER" /> <result column="is_delete" property="isDelete" jdbcType="SMALLINT" /> </resultMap>--> <select id="getByIdSql" parameterType="java.lang.Long" resultType="User"> select * from user where 1=1 and id=#{id,jdbcType=BIGINT} </select> </mapper>

③ mapper编写自定义接口

@Mapper public interface UserMapper extends BaseMapper<User> { User getByIdSql(Long id); }

④测试完成

原文链接:https://blog.csdn.net/qq_41908550/article/details/107223610?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165277096216782388094798%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=165277096216782388094798&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~times_rank-12-107223610-null-null.nonecase&utm_term=%E5%AE%9E%E7%94%A8%E6%95%99%E7%A8%8B

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
文明发言,共建和谐米科社区
提交
头像

昵称

取消
昵称表情图片