文章目录
MyBatisPlus
MyBatisPlus可以节省我们大量工作时间,所有的CRUD代码它都可以自动化完成!
简介
MyBatis、本来就是简化JDBC操作的!
MyBatisPlus,简化MyBatis
官网:https://baomidou.com/
一、特性
- 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
- 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
- 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
- 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
- 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
- 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
- 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
- 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
- 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
- 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
- 内置性能分析插件:可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
- 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作
二、快速入门
使用第三方组件:
- 导入对应的依赖
- 研究依赖如何配置
- 代码如何编写
- 提高扩展能力!
步骤
-
创建数据库 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(乐观锁),delete(逻辑删除),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 是自己开发的,并非官方的--> <!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.1</version> </dependency>
说明:我们使用mybatis-plus可以节省我们大量的代码,尽量不要同时导入mybatis和mybatis-plus!会出错版本差异!
-
连接数据库
#mysql 5 驱动不同 com.mysql.jdbc.Driver spring.datasource.username=root spring.datasource.password=1127 spring.datasource.url=jdbc:mysql://localhost:3307/mybatis-plus?useSSL=false&useUnicode=true&characterEncoding=utf-8 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver #mysql 8 驱动 com.mysql.cj.jdbc.Driver,需要增加时区的配置 serverTimezone=GMT%2B8
传统方式pojo-dao(连接mybatis,配置mapper.xml文件)-service-controller
-
使用了mybatis-plus之后
-
pojo
@Data @AllArgsConstructor @NoArgsConstructor public class User { private Long id; private String name; private Integer age; private String email; }
-
mapper接口
//在对应的Mapper上面继承基本的类 BaseMapper @Repository //代表持久层 public interface UserMapper extends BaseMapper<User> { //所有的CURD操作都已经编写完成了 //不需要像以前的配置一大堆文件了 }
-
注意:需要在主启动类上去扫描mapper包下的所有接口!
//扫描mapper文件 @MapperScan("com.example.mybatis_plus") @SpringBootApplication public class MybatisPlusApplication { public static void main(String[] args) { SpringApplication.run(MybatisPlusApplication.class, args); } }
-
测试
//继承BaseMapper,所有的方法都来自父类,我们也可以编写自己的扩展方法 @Autowired private UserMapper userMapper; @Test void contextLoads() { //参数是一个Wrapper,条件构造器,这里我们先不用null //查询全部用户 List<User> users = userMapper.selectList(null); users.forEach(System.out::println); }
-
测试运行,成功查到所有的信息
小结
通过上述简单的几步,就可以实现 User 表的 CRUD 功能,以往的 XML 文件不再需要
- 集成
MyBatis-Plus
非常的简单,只需要引入对应的依赖,并配置 mapper 扫描路径即可
三、配置日志
虽然我们已经实现了基本的CRUD功能,但是相应的sql语句是不可见的,为了看每条sql是怎么执行的,我们必须查看日志;
MyBatis Plus
本身集成了log日志功能,我们打开即可
接下来在application.properties
中启动MyBatis plus
本身日志;我们也可以使用第三方的日志,但是需要导入相应的依赖
#配置日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
我们再次运行上述的查询全部用户方法,即可查看到所执行sql的相关日志信息
四、CRUD及其拓展
1. 插入insert & 主键生成策略
//测试插入
@Test
void testInsert() {
User user = new User();
user.setName("Azmat");
user.setAge(22);
user.setEmail("2271427740@qq.com");
int result = userMapper.insert(user); //帮我们自动生成id
System.out.println(result);
System.out.println(user);
}
测试一下,查看日志信息,成功插入数据,且可以看到为我们自动生成了一个ID
我们并没有设置主键id
的值,但是MyBatis Plus
自动为我们生成了一个id,这个id是如何生成的?
1. 主键生成策略
系统唯一ID(主键)是我们在设计一个系统的时候常常会遇见的问题,生成ID的方法有很多,适应不同的场景、需求以及性能要求;有些比较复杂的系统甚至会有多个ID生成的策略
分布式系统唯一ID生成方案汇总:https://www.cnblogs.com/haoxinyue/p/5208136.html
在MyBatis Plus
中,生成主键id
的方法是 雪花算法,我们也可以通过@TableId
注解设置修改使用其他的生成策略,我们看看该注解的源码
可以发现这是一个枚举类,其中有五种方式,默认生成ID的方式是ASSIGN_ID
,底层也就是通过雪花算法
实现的
AUTO
:数据库ID自增NONE
:未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT)INPUT
:插入前自己设置主键的值ASSIGN_ID
:分布式全局唯一ID(长整型类型)ASSIGN_UUID
:32位UUID字符串
接下来我们通过
@TableID
注解指定其他策略试试
2.主键自增AUTO
我们在我们实体类的主键上可以指定所需的方式,这里配置为主键自增
方式
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
@TableId(type = IdType.AUTO)
private Long id;
private String name;
private Integer age;
private String email;
}
同时要在数据库中设置主键id
自增,然后保存。否则会报错
再次测试一下上述插入方法,成功插入,且新插入user的id实现了自增
可以发现每次id都+1,成功实现了主键自增功能
3.手动输入INPUT
将主键id上的注解更改为
@TableId(type = IdType.INPUT)
因为我们的数据表设置了主键自增,查看日志信息,发现id为null,因此我们需要手动设置id
//测试插入
@Test
void testInsert() {
User user = new User();
user.setId(6L); //手动录入id
user.setName("alem");
user.setAge(22);
user.setEmail("2271427740@qq.com");
int result = userMapper.insert(user);
System.out.println(result);
System.out.println(user);
}
再次测试,成功插入指定id用户
2. 更新update & 自动填充功能
1. 测试更新
在测试类中新建一个方法,注意
updateById()
方法传入的参数为User对象
//测试插入
@Test
void testUpdate() {
User user = new User();
//通过条件自动自动拼接动态sql
user.setId(6L);
user.setName("abdu++");
int result = userMapper.updateById(user); //参数是一个对象
System.out.println(result);
}
运行该测试方法,成功更新指定用户的信息
总结:在MyBatisPlus
中,所有的sql都是自动动态配置的(动态sql)
2. 自动填充
数据库写入一些东西时,比如创建时间、修改时间!更新这些字段时,一般都是自动化完成的,不希望自己手动更新
在阿里巴巴开发手册中,所有的数据库表几乎都有两个字段:
gmt_create
、gmt_modified
;这两个字段都是自动化更新的接下来我们来实现一下这两个字段的自动填充
方式一:数据库级别
1. 首先在数据库表user
中新增两个字段crate_time
、update_time
;
默认值都设置为CURRENT_TIMESTAMP
,updata_time
字段勾选根据当前时间戳更新,然后保存
2.同步实体类,新增两个字段
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
@TableId(type = IdType.INPUT)
private Long id;
private String name;
private Integer age;
private String email;
private Date createTime;
private Date updateTime;
}
3.运行测试
修改一下testUpdate
方法后运行测试
//测试插入
@Test
void testUpdate() {
User user = new User();
//通过条件自动自动拼接动态sql
user.setId(6L);
user.setName("abdu++");
user.setAge(32);
int result = userMapper.updateById(user); //参数是一个对象
System.out.println(result);
}
方式二:代码级别
1. 首先删除数据表中上述两个字段的默认值以及update_time
的更新操作
2. 我们可以在实体类字段属性上添加注解@TableField
实现自动填充,来看看该注解的源码
其中有个fill
属性用于设置字段自动填充策略FieldFill
,我们在看看可以设置的策略
可以看到,FiledFill
同样是个枚举类,有四种填充策略,默认是DEFAULT
不处理
接下来我们使用该注解在字段上进行设置
- 在
createTime
时填充策略为INSERT
:插入填充字段 - 在
updateTime
时填充策略位INSER_UPDATE
:插入和更新时填充字段
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
@TableId(type = IdType.AUTO)
private Long id;
private String name;
private Integer age;
private String email;
//字段添加填充内容
@TableField(fill = FieldFill.INSERT)
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
}
3. 编写自动填充处理器处理这个注解
在主程序同级目录下新建
handler
包,其中创建自己的处理器MyMetaObjectHandler
类,继承MetaObjectHandler
接口,重写其方法
@Slf4j
@Component //放置IOC容器中
public class MyMetaObjectHandler implements MetaObjectHandler {
//插入时的填充策略
@Override
public void insertFill(MetaObject metaObject) {
log.info("start insert fill.....");
//在插入时填充`crateTime`和`updateTime`字段
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);
}
}
4. 运行测试
首选运行插入方法InsertUser
//测试插入
@Test
void testInsert() {
User user = new User();
user.setName("alem");
user.setAge(22);
user.setEmail("2271427740@qq.com");
int result = userMapper.insert(user);
System.out.println(result);
System.out.println(user);
}
运行后可以发现新插入的用户两个时间与其他不同,实现了自动填充更新
然后我们update一下新插入的用户试试
//测试插入
@Test
void testUpdate() {
User user = new User();
//通过条件自动自动拼接动态sql
user.setId(1507204624015212550L);
user.setName("艾孜");
user.setAge(22);
int result = userMapper.updateById(user); //参数是一个对象
System.out.println(result);
}
运行完可以看到update_time
成功更新
3. 查询select & 分页查询插件
1. 测试查询
1、通过id查询用户
//查询指定用户
@Test
public void selectUserByID() {
User user = userMapper.selectById(1);
System.out.println(user);
}
2、查询批量用户
//批量查询用户
@Test
public void selectUserByBatchID() {
List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 6, 5, 3));//参数为列表集合
users.forEach(System.out::println);
}
3、条件查询
//条件查询
@Test
public void selectUserWithCondition() {
HashMap<String, Object> map = new HashMap<>();
//自定义查询条件
map.put("name","alem");
map.put("age","22");
List<User> users = userMapper.selectByMap(map);
users.forEach(System.out::println);
}
2. 分页查询
在MyBatisPlus内部内置了分页插件,我们稍加配置即可使用
1、配置拦截器组件
在主程序同级目录下新建
config
包,其中新建MyBatisPlusConfig
,其中配置分页插件同时将扫描包注解
@MapperScan("com.zsr.mapper")
从我们主程序转移到该配置类,更加规范
@MapperScan("com.example.mybatis_plus")//声明Mapper扫描器
@EnableTransactionManagement
@Configuration // 声明配置类
public class MyBatisPlusConfig {
//注册bean
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
//创建插件管理器
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
//添加乐观锁插件
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
//添加分页插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
// 返回插件管理器
return interceptor;
}
}
2、直接使用page对象进行分页操作
在测试类中测试分页查询
@SpringBootApplication
public class MybatisPlusApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisPlusApplication.class, args);
}
}
成功查出1~3用户,同时可以发现本质还是使用limit
进行分页
4. 删除 & 逻辑删除
1. 测试删除
//删除指定id用户
@Test
public void deleteByID() {
userMapper.deleteById(5);
}
//批量删除
@Test
public void deleteByBatchID() {
userMapper.deleteBatchIds(Arrays.asList(3,4));
}
//条件删除
@Test
public void deleteByCondition() {
HashMap<String, Object> map = new HashMap<>();
map.put("name", "艾孜4");//自定义条件:删除所有name为zsr的
map.put("id", "1");//自定义条件:删除所有name为zsr的
userMapper.deleteByMap(map);
}
2. 逻辑删除
物理删除
:从数据库中直接移除
逻辑删除
:数据库中没有移除,而是通过一个变量来让其失效(delete=0 —> delete=1)
1、在数据表中增加一个deleted
字段,默认值0
注意:字段不能使数据库中的关键字,如delete
2、同步pojo实体类
用
@TableLogic
注解标名这是逻辑删除
@TableLogic //逻辑删除
private Integer deleted;
3、配置逻辑删除组件
首先
application.properties
添加相应的配置
#配置逻辑删除
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0
- 已删除
deleted
=1 - 未删除
deleted
=0
4、测试
//删除指定5号用户
@Test
public void deleteByID() {
userMapper.deleteById(5);
}
可以看到,我们执行的删除方法本质上是更新操作,更新了deleted
的值,,刷新user表看看
可以看到1号用户并没有删除,记录仍在数据库,只是deleted
变为1,代表已删除
我们查询所有用户试试
@Test
void contextLoads() {
//参数是一个wrapper条件构造器,这里先不用,写null
//查询全部用户
List<User> users = userMapper.selectList(null);
users.forEach(System.out::println);
}
可以看到,查询的时候带了条件deleted
=0,即未删除的用户才能被查询到;自动过滤被逻辑删除的字段,所以我们查询不到用户1,因为已经逻辑删除
五、乐观锁插件
乐观锁
:故名思意十分乐观,它总是认为不会出现问题,无论干什么不去上锁!如果出现了问题,再次更新值测试
悲观锁
:故名思意十分悲观,它总是认为总是出现问题,无论干什么都会上锁!再去操作!
1. 实现方式
当要更新一条记录的时候,希望这条记录没有被别人更新
乐观锁实现方法:
- 取出记录时,获取当前version
- 更新时,带上这个version
- 执行更新时,set version = newVersion where version = oldVersion
- 如果version不对,就更新失败
-- A 先查询,获得版本号 version = 1
update user set name = "zsr", version = version + 1
where id = 2 and version = 1
-- B 如果此时B线程抢先完成,这个时候 version = 2,会导致 A 修改失败!
update user set name = "zsr", version = version + 1
where id = 2 and version = 1
2. 测试乐观锁插件
1、添加version字段
首先给数据库表添加一个version
字段,设置默认值为1
查看是否添加成功
2、同步实体类
注意添加
@version
注解@Version //代表这是一个乐观锁 private Integer version;
3、注册乐观锁组件
在主程序同级目录下新建
config
包,其中新建MyBatisPlusConfig
注册乐观锁插件
@EnableTransactionManagement
@Configuration
public class MyBatisPlusConfig {
//注册乐观锁插件
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
}
4、测试
测试一下,分别测试乐观锁成功和失败的两种情况
1、首先测试单线程对用户进行修改的情况
//单线程测试乐观锁成功
@Test
public void TestOptimisticLockerInnerInterceptor_success() {
//获取用户
User user = userMapper.selectById(1);
//修改用户信息
user.setName("Nizamat");
user.setEmail("aize@qq.com");
//执行更新操作
userMapper.updateById(user);
}
运行测试一下,修改成功信息,查看打印的日志
可以看到,第一次的查询和第二次的更新操作的sql语句都附加了version
信息,第一次查出来version为1,更新操作时,version+1更改为2,这就是乐观锁的作用,修改成功
2、再测试两个线程都对用户进行修改的情况
//测试多线程修改
@Test
public void TestOptimisticLockerInnerInterceptor_fail() {
//线程1,设置了值但未修改
User user1 = userMapper.selectById(1);
user1.setName("艾孜1");
user1.setEmail("6379@qq.com");
//线程2,设置了值且更新
User user2 = userMapper.selectById(1);
user2.setName("艾孜2");
user2.setEmail("63792@qq.com");
userMapper.updateById(user2);
//线程1进行更新:如果没有乐观锁就会覆盖线程2设置的值
userMapper.updateById(user1);
}
运行测试一下,查看日志信息,可以看到线程2的更新操作成功了,线程1并未成功,这是因为线程2更新前,version
的值为2,更新后变为3,但是线程1最后的更新操作的附加条件version
仍未2,与当下version
不同,所以更新失败
同时可以查看user表,最终结果是线程2修改的结果
六、性能分析插件
开发过程中,会遇到一些慢sql,我们通常需要将其提取出来并进行相应的优化,优化查询效率;
- 作用:用于输出每条SQL语句执行的时间,如果sql语句的时间超过我们指定的时间,就可以停止运行
该插件 3.2.0
以上版本移除推荐使用第三方扩展 执行 SQL 分析打印
功能
七、条件构造器
1. 条件查询
一、简单条件运算符
eq:等于 =
ne:不等于 <>
gt:大于 >
ge:大于等于 >=
lt:小于 <
le:小于等于 <=
二、逻辑运算符
or:拼接or
and:
nest
三、模糊查询between:between 值1 and 值2
notbetween:notbetween 值1 and 值2
like:like ‘%值%’
not like:notlike ‘%值%’
likeLeft:like ‘%值’
likeRight:like ‘值%’
isNull:字段为空
isNotNull:字段不为空
in:字段 in(value1,value2 …)
notIn:字段 notIn(value1,value2 …)
1、查询name不为空,邮箱不为空且年龄>=20的用户
@Test
void test1() {
//查询name不为空,邮箱不为空、年龄>=22的用户
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.isNotNull("name")
.isNotNull("email")
.ge("age", 22);
userMapper.selectList(wrapper).forEach(System.out::println);
}
运行测试,查看输入信息,可以发现附加了我们所需的条件语句
2、查询名字为Jack
@Test
void test2() {
//查询名字为Jack
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("name","Jack");
User user = userMapper.selectOne(wrapper); //查询一个数据,出现多个结果使用List或者Map
System.out.println(user);
}
3、查询年龄小于20或大于25的用户
//查询年龄小于20或大于25的用户
@Test
public void test3() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
//链式编程
wrapper.lt("age", 18).or().gt("age", 22);
Long count = userMapper.selectCount(wrapper);
System.out.println(count);
}
4、查询年龄介于20~30之间的用户
//查询年龄介于20~30之间的用户
@Test
public void test4() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
//链式编程
wrapper.between("age", 20, 30);
userMapper.selectCount(wrapper);//返回结果数
}
5、模糊查询、查询名字中不包含J的,且邮箱以t开头的
//查询名字中不包含J的,且邮箱以t开头的
@Test
public void test5() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
//链式编程
wrapper
.notLike("name", "J")
.likeRight("email", "t");//相当于右边加一个百分号:t%
List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);
maps.forEach(System.out::println);
}
2. 子查询
inSql
:字段 in(sql语句)notInSql
:字段 notIn(sql语句)
//子查询
@Test
public void test6() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
//链式编程
wrapper.inSql("id", "select id from user where id<3");
List<Object> objects = userMapper.selectObjs(wrapper);
objects.forEach(System.out::println);
}
3. 分组查询
groupBy
:group by 字段,…having
:having(sql语句)
//根据update_time分组查询
@Test
public void test8() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
//链式编程
wrapper.select("count(*)","update_time")
.groupBy("update_time");
userMapper.selectObjs(wrapper);
}
4. 排序查询
orderByAsc
:order by 字段,… ascorderByDesc
:order by 字段,… desc
1、按id降序排序查询
//按id降序排序查询
@Test
public void test7() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.orderByDesc("id");//id降序排序查询
//wrapper.orderByAsc("id");//id降序升序查询
userMapper.selectObjs(wrapper);
}
八、代码自动生成器
AutoGenerator
是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。
1、添加依赖
<!--代码生成器-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.2.0</version>
</dependency>
2.编写自动生成代码
package com.example.createcode;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import java.util.Scanner;
// 演示例子,执行 main 方法控制台输入模块表名回车自动生成对应项目目录中
public class Generator {
/**
* <p>
* 读取控制台内容
* </p>
*/
public static String scanner(String tip) {
Scanner scanner = new Scanner(System.in);
StringBuilder help = new StringBuilder();
help.append("请输入" + tip + ":");
System.out.println(help.toString());
if (scanner.hasNext()) {
String ipt = scanner.next();
if (StringUtils.isNotEmpty(ipt)) {
return ipt;
}
}
throw new MybatisPlusException("请输入正确的" + tip + "!");
}
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("Azmat");//设置作者名
gc.setOpen(false); //设置是否打开资源管理器
gc.setFileOverride(true);//是否覆盖原来生成的代码
gc.setBaseResultMap(true); // xml resultmap
gc.setBaseColumnList(true); // xml columlist
gc.setServiceName("%sService"); //去Service的I前缀
gc.setIdType(IdType.ID_WORKER);//设置主键生成策略
gc.setDateType(DateType.ONLY_DATE);//设置日期类型
gc.setSwagger2(true); //设置自动配置swagger文档,实体属性Swagger2注解
//将全局配置装入自动代码生成器
mpg.setGlobalConfig(gc);
//2.数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://localhost:3307/mybatis-plus?&characterEncoding=utf8&useSSL=false&serverTimezone=UTC");
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("密码");
mpg.setDataSource(dsc);
//3.包配置
PackageConfig pc = new PackageConfig();
pc.setModuleName("blog");//设置模块名
pc.setParent("com.example");//设置放置的包名
pc.setController("controller");//controller层包名
pc.setEntity("pojo" );//pojo层包名
pc.setMapper("mapper");//mapper层包名
pc.setService("service" );//service层包名
pc.setServiceImpl("service.impl");//实现类
//将包配置装入自动代码生成器
mpg.setPackageInfo(pc);
//4.策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setNaming(NamingStrategy.underline_to_camel);//设置包命名的规则:下划线转驼峰命名
strategy.setColumnNaming(NamingStrategy.underline_to_camel);//设置数据库字段命名规则
strategy.setEntityLombokModel(true);//开启自动生成lombok
strategy.setRestControllerStyle(true);
// 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");
strategy.setRestControllerStyle(true);//开启restful驼峰命名格式
// 写于父类中的公共字段
strategy.setSuperEntityColumns("id");
strategy.setInclude(scanner("表名,多个英文逗号分割").split(","));//设置要映射的数据表名
strategy.setControllerMappingHyphenStyle(true);//设置请求链接格式,例如localhost:8080/hello_id_2
strategy.setTablePrefix(pc.getModuleName() + "_");
mpg.setStrategy(strategy);
mpg.setTemplateEngine(new FreemarkerTemplateEngine());
//执行代码构造器
mpg.execute();
}
}
3.测试
表名,多个表可以英文逗号分割
以下生成的代码