6.Mybatis-plus简介
Mybatis-plus简介
不在需要手写mapper和mapper.xml文件,只需要创建mapper接口,集成baseMappoer即可
Quick Start
- 创建数据库环境
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');
- 新建SpringBoot项目,选择Spring Web,Lombok依赖
- 添加依赖
<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>
</dependency>
- 更改配置文件
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/demo?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
application:
name: plus-test
server:
port: 8090
- 创建pojo类和mapper方法,mapper方法继承BaseMapper<表对象>,添加持久层依赖@Repository
- 测试类调用mapper中的方法
配置日志输出
添加配置文件
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
主键策略
主键自动生成
可以在pojo类中主键字段上加入注解 @TableId(type = IdType.AUTO)
package com.baomidou.mybatisplus.annotation;
public enum IdType {
AUTO(0), //在原来的基础上自动加一,前提是表字段为自增
NONE(1), //3.4.2版本默认的,id为0,如果数据库中已经存在0,则报错
INPUT(2), //必须要输入主键
ASSIGN_ID(3),
ASSIGN_UUID(4),
@Deprecated
ID_WORKER(3), //全局唯一ID
@Deprecated
ID_WORKER_STR(3), //ID_word的字符串表示法
@Deprecated
UUID(4); //全局唯一ID uuid
private final int key;
private IdType(int key) {
this.key = key;
}
public int getKey() {
return this.key;
}
}
表中新建表(create_time)和修改表字段(update_time)更新
数据库实现
代码实现
-
先删除之前数据库中的触发器和默认值,只创建列名
-
在字段上声明注解
@TableField(fill = FieldFill.INSERT)
private Date create_time;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date update_time;
- 创建MyMetaObjectHandler对象实现MetaObjectHandler接口
@Component
@Slf4j
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
log.info("start insert !");
this.setFieldValByName("create_time",new Date(),metaObject);
this.setFieldValByName("update_time",new Date(),metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
log.info("start update !");
this.setFieldValByName("update_time",new Date(),metaObject);
}
}
乐观锁
-
表中加入version字段 ,int类型,默认值为1
-
在pojo类中version上声明注解@Version
-
在config下创建配置类
@MapperScan("com.my.mapper")
@EnableTransactionManagement
@Configuration
public class MybatisPlusConfig {
//注册乐观锁插件
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
}
- 测试执行结果
@Test
void t3(){
Userinfo userinfo = userMapper.selectById(2);
userinfo.setName("aaa");
Userinfo userinfo2 = userMapper.selectById(2);
userinfo2.setName("bbb");
userMapper.updateById(userinfo2);
userMapper.updateById(userinfo);
}
分页锁插件
- 在配置类中注册bean对象
//分页操作插件
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor2() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
return interceptor;
}
- 测试使用
@Test
void t4(){
Page<Userinfo> objectPage = new Page<>(1,3);
userMapper.selectPage(objectPage,null);
objectPage.getRecords().forEach(System.out::println);
}
逻辑删除
- 表中添加字段deleted,int类型,默认为1
- pojo类中填加字段,注解@TableLogic
- 测试使用(原先的删除变成的update,查找自动添加后置条件(deleted = 0)
性能分析插件
mybatis-plus3.2版本移除了性能分析插件
之前版本的使用
- 添加配置类中的组件
//SQL执行效率插件
@Bean
@Profile({"dev","test"})//开启环境保护,保证我们的效率
public PerformanceInterceptor performanceInterceptor(){
PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
performanceInterceptor.setMaxTime(1);//设置执行sql的最大时间,如果超过则不执行
performanceInterceptor.setFormat(true);//开启sql语句格式化
return performanceInterceptor;
}
-
#设置开发环境 spring.profiles.active: dev
-
测试使用
条件构造器(QueryWrapper)
Wrapper 的作用就是用于定义各种各样的条件(where)。所以不管是查询、更新、删除都会用到Wrapper。
封装关系
Wrapper 条件构造抽象类
-- AbstractWrapper 查询条件封装,用于生成 sql 中的 where 语句。
-- QueryWrapper Entity 对象封装操作类,用于查询。
-- UpdateWrapper Update 条件封装操作类,用于更新。
-- AbstractLambdaWrapper 使用 Lambda 表达式封装 wrapper
-- LambdaQueryWrapper 使用 Lambda 语法封装条件,用于查询。
-- LambdaUpdateWrapper 使用 Lambda 语法封装条件,用于更新。
常用条件
- ( =, <>, >, >=, <, <= )
eq(R column, Object val); // 等价于 =,例: eq("name", "老王") ---> name = '老王'
ne(R column, Object val); // 等价于 <>,例: ne("name", "老王") ---> name <> '老王'
gt(R column, Object val); // 等价于 >,例: gt("name", "老王") ---> name > '老王'
ge(R column, Object val); // 等价于 >=,例: ge("name", "老王") ---> name >= '老王'
lt(R column, Object val); // 等价于 <,例: lt("name", "老王") ---> name < '老王'
le(R column, Object val); // 等价于 <=,例: le("name", "老王") ---> name <= '老王'
- between、not between、in、not in
between(R column, Object val1, Object val2);
// 等价于 between a and b, 例: between("age", 18, 30) ---> age between 18 and 30
notBetween(R column, Object val1, Object val2);
// 等价于 not between a and b, 例: notBetween("age", 18, 30) ---> age not between 18 and 30
in(R column, Object... values);
// 等价于 字段 IN (v0, v1, ...),例: in("age",{1,2,3}) ---> age in (1,2,3)
notIn(R column, Object... values);
// 等价于 字段 NOT IN (v0, v1, ...), 例: notIn("age",{1,2,3}) ---> age not in (1,2,3)
inSql(R column, Object... values);
// 等价于 字段 IN (sql 语句), 例: inSql("id", "select id from table where id < 3") ---> id in (select id from table where id < 3)
notInSql(R column, Object... values);
// 等价于 字段 NOT IN (sql 语句)
- 模糊匹配:(like)
like(R column, Object val);
// 等价于 LIKE '%值%',例: like("name", "王") ---> name like '%王%'
notLike(R column, Object val);
// 等价于 NOT LIKE '%值%',例: notLike("name", "王") ---> name not like '%王%'
likeLeft(R column, Object val); // 等价于 LIKE '%值',例: likeLeft("name", "王") ---> name like '%王'
likeRight(R column, Object val); // 等价于 LIKE '值%',例: likeRight("name", "王") ---> name like '王%'
- 分组、排序:(group、having、order)
groupBy(R... columns); // 等价于 GROUP BY 字段, ..., 例: groupBy("id", "name") ---> group by id,name
orderByAsc(R... columns); // 等价于 ORDER BY 字段, ... ASC, 例: orderByAsc("id", "name") ---> order by id ASC,name ASC
orderByDesc(R... columns); // 等价于 ORDER BY 字段, ... DESC, 例: orderByDesc("id", "name") ---> order by id DESC,name DESC
having(String sqlHaving, Object... params); // 等价于 HAVING ( sql语句 ), 例: having("sum(age) > {0}", 11) ---> having sum(age) > 11
- 拼接、嵌套 sql:(or、and、nested、apply)
or(); // 等价于 a or b, 例:eq("id",1).or().eq("name","老王") ---> id = 1 or name = '老王'
or(Consumer<Param> consumer); // 等价于 or(a or/and b),or 嵌套。例: or(i -> i.eq("name", "李白").ne("status", "活着")) ---> or (name = '李白' and status <> '活着')
and(Consumer<Param> consumer); // 等价于 and(a or/and b),and 嵌套。例: and(i -> i.eq("name", "李白").ne("status", "活着")) ---> and (name = '李白' and status <> '活着')
nested(Consumer<Param> consumer); // 等价于 (a or/and b),普通嵌套。例: nested(i -> i.eq("name", "李白").ne("status", "活着")) ---> (name = '李白' and status <> '活着')
apply(String applySql, Object... params); // 拼接sql(若不使用 params 参数,可能存在 sql 注入),例: apply("date_format(dateColumn,'%Y-%m-%d') = {0}", "2008-08-08") ---> date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")
last(String lastSql); // 无视优化规则直接拼接到 sql 的最后,可能存若在 sql 注入。
exists(String existsSql); // 拼接 exists 语句。例: exists("select id from table where age = 1") ---> exists (select id from table where age = 1)
- QueryWrapper 条件:
select(String... sqlSelect); // 用于定义需要返回的字段。例: select("id", "name", "age") ---> select id, name, age
select(Predicate<TableFieldInfo> predicate); // Lambda 表达式,过滤需要的字段。
lambda(); // 返回一个 LambdaQueryWrapper
- UpdateWrapper 条件:
set(String column, Object val); // 用于设置 set 字段值。例: set("name", null) ---> set name = null
setSql(String sql); // 用于设置 set 字段值。例: setSql("name = '老李头'") ---> set name = '老李头'
lambda(); // 返回一个 LambdaUpdateWrapper
代码生成器
- 添加依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.1</version>
</dependency>
- 创建测试类Autocode,执行代码
package com.my;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.FieldFill;
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.po.TableFill;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import java.util.ArrayList;
public class AutoCode {
public static void main(String[] args) {
//构建代码生成器对象
AutoGenerator autoGenerator = new AutoGenerator();
/*配置策略*/
//全局配置
GlobalConfig config = new GlobalConfig();
//代码生成的目录
String path = System.getProperty("user.dir");
//设置代码最终输出的目录
config.setOutputDir(path + "");
//设置作者
config.setAuthor("");
//配置是否打开目录,false 为不打开
config.setOpen(false);
//是否覆盖已有的
config.setFileOverride(false);
//去除service前缀
config.setServiceName("%sService");
//主键
config.setIdType(IdType.ID_WORKER);//默认的
//设置时间类型
config.setDateType(DateType.ONLY_DATE);//只显示日期
//是否生成Swagger文档
config.setSwagger2(false);
//设置策略
autoGenerator.setGlobalConfig(config);
/*设置数据源*/
DataSourceConfig dataSourceConfig = new DataSourceConfig();
dataSourceConfig.setDriverName("com.mysql.cj.jdbc.Driver"); //驱动
dataSourceConfig.setUrl("jdbc:mysql://127.0.0.1:3306/demo?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8"); //连接地址
dataSourceConfig.setUsername("root"); //数据库用户名
dataSourceConfig.setPassword("123456"); //数据库密码
dataSourceConfig.setDbType(DbType.MYSQL); //数据库类型
//设置数据源
autoGenerator.setDataSource(dataSourceConfig);
/*项目包的配置*/
PackageConfig packageConfig = new PackageConfig();
packageConfig.setModuleName("my");//模块名
packageConfig.setParent("com.my");//设置父目录
packageConfig.setEntity("entity");//实体类包名
packageConfig.setMapper("mapper");//mapper映射文件包名
packageConfig.setService("service");//业务接口包名
packageConfig.setServiceImpl("serviceIml");//业务层实现类包名
packageConfig.setController("controller");//控制层包名
//添加项目包配置
autoGenerator.setPackageInfo(packageConfig);
/*策略配置*/
StrategyConfig strategyConfig = new StrategyConfig();
strategyConfig.setInclude("userinfo");//表名
strategyConfig.setNaming(NamingStrategy.underline_to_camel);//配置数据表与实体类名之间映射的策略
strategyConfig.setColumnNaming(NamingStrategy.underline_to_camel);//配置数据表的字段与实体类的属性名之间映射的策略
strategyConfig.setEntityLombokModel(true);//是否启用Lombok
strategyConfig.setLogicDeleteFieldName("deleted");//逻辑删除字段名
TableFill field1 = new TableFill("create_time", FieldFill.INSERT);//自动填充的字段 -数据插入时间
TableFill field2 = new TableFill("update_time", FieldFill.INSERT_UPDATE);//自动填充的字段 -数据修改时间
//自动填充配置集合
ArrayList<TableFill> list = new ArrayList<>();
list.add(field1);
list.add(field2);
strategyConfig.setTableFillList(list);
strategyConfig.setVersionFieldName("version");//乐观锁
strategyConfig.setRestControllerStyle(true);//配置 rest风格的控制器
strategyConfig.setControllerMappingHyphenStyle(true);//配置驼峰转连字符
//添加策略配置
autoGenerator.setStrategy(strategyConfig);
//执行
autoGenerator.execute();
}
}
版权声明:
本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自
郭远的博客空间!
喜欢就支持一下吧
打赏
微信
支付宝