Mybatis-plus
简介 | MyBatis-Plus (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依赖
<!--mybatis-plus--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.3</version> </dependency> <!--mysql--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency>
-
写入相应的pojo层和dao层
pojo import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.io.Serializable; @Data @NoArgsConstructor @AllArgsConstructor public class user implements Serializable { private Integer id; private String name; private Integer age; private String email; } dao
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zhoulei.mybatis_plus01.pojo.user;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
//@Mapper//也可以不在启动类中配置包扫描,在每个Mapper上面配置@Mapper,相当与mapper映射
@Repository//表示使Dao层
public interface userMapper extends BaseMapper<user> {
}
- 测试
@SpringBootTest
class MybatisPlus01ApplicationTests {
@Autowired
private userMapper userMapper;
@Test
public void selectAll(){
// List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 参数类型使一个Wrapper类型,表示是一个条件构造器
// 下面相当与 select * from user where null;
List<user> users = userMapper.selectList(null);
users.forEach(System.out::println);
}
}
## CRUD扩展雪花算法
雪花算法
[分布式唯一ID解决方案-雪花算法 - 掘金 (juejin.cn)](https://juejin.cn/post/6916882326996090894)
```java
@Data
@NoArgsConstructor
@AllArgsConstructor
public class user implements Serializable {
//默认是雪花算法,同时自己也可以改变为自增ID
private Integer id;
private String name;
private Integer age;
private String email;
}
public enum IdType {
AUTO(0), //数据库id自增
NONE(1), //未设置主键
INPUT(2), //手动输入
ASSIGN_ID(3), //表示程序分配一个数字型主键
ASSIGN_UUID(4); //表示程序分配一个 UUID 作为主键
}
IdType4种值的表示MybatisPlus 主键策略(type=IdType.ASSIGN_ID等详解) - 双间 - 博客园 (cnblogs.com)
## 配置日志
```yml
#开启日志
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
public enum IdType {
AUTO(0), //数据库自增
NONE(1), //不管
INPUT(2),//手动插入,与不管类似
/* 以下3种类型、只有当插入对象ID 为空,才自动填充。 */
/**
* 分配ID (主键类型为number或string),
* 默认实现类 {@link com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator}(雪花算法)
*/
ASSIGN_ID(3),
/**
* 分配UUID (主键类型为 string)
* 默认实现类 {@link com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator}(UUID.replace("-",""))
*/
ASSIGN_UUID(4),
}
IdType type() default IdType.NONE;
自动填充
创建时间,修改时间!这些操作一般都是自动化完成的,我们不希望手动更新!
阿里巴巴开发手册:所有的数据库表:gmt_create,gmt_modified,几乎所有的表都要配置上!而且
需要自动化
方式一:数据库级别(不建议在工作中使用)
在数据中新增两个字段,并将其默认值为current_timestamp,数据类型为datetime
方式二:代码级别
将表还原,避免数据的级别的自动填入对我们造成影响
实现:
-
需要在实现自动注入的字段上面添加@TableField注解,使用fill属性
public enum FieldFill { DEFAULT, //什么都不干 INSERT, //插入时填充 UPDATE, //更新时填充 INSERT_UPDATE; //在插入和更新的填充 }
-
编写处理类来处理注解
@Slf4j @Component //注意一定要将这个类放入到IOC容器中,在识别注解的时候就会利用反射机制运行到这个处理类 public class MyMetaobjectHandler implements MetaObjectHandler { @Override public void insertFill(MetaObject metaObject) { //* @param fieldName java bean属性名 //* @param fieldVal java bean属性值 //* @param metaObject元对象参数 log.info("start insert ...."); this.setFieldValByName("createTime",new Date(),metaObject ); this.setFieldValByName("updateTime",new Date(),metaObject ); } @Override public void updateFill(MetaObject metaObject) { log.info("start update ...."); this.setFieldValByName("updateTime",new Date(),metaObject ); } }
-
测试
-
查看数据库,注意字段值的变化.
乐观锁处理
乐观锁:十分乐观,它总是认为自己不会出现问题,所以在执行前不会去加锁,如果出现错误就在次去更新值去测试.
悲观锁:十分的悲观,它总是认为自己做什么都会出现问题,所以在执行之前都会加上锁.在去操作
使用乐观锁,一般都会加上一个version字段.
当要更新一条记录的时候,希望这条记录没有被别人更新
乐观锁实现方式:
取出记录时,获取当前 version
更新时,带上这个 version
执行更新时, set version = newVersion where version = oldVersion
如果 version 不对,就更新失败
举例说明:
线程A要执行的SQL语句
update form user set name="aaa" ,version =version+1 where id='1' and version =1;
在线程A还没有执行这个SQL语句之前,来了一个线程B同样执行这条SQL语句,会导致在线程A执行时version!=1,SQL语句执行错误.
在代码中实现乐观锁
-
在数据库表中添加version字段,并将其defualt值为1
-
在实体类中同步数据库字段,并在version字段上面添加@Version注解
@Version //乐观锁version注解 private Integer version;
-
注册组件
-
spring xml 方式:
<bean class="com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor" id="optimisticLockerInnerInterceptor"/> <bean id="mybatisPlusInterceptor" class="com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor"> <property name="interceptors"> <list> <ref bean="optimisticLockerInnerInterceptor"/> </list> </property> </bean>
-
spring boot 注解方式:
@Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); return interceptor; }
-
测试:
成功:
@Test
public void versionTest (){
user user= userMapper.selectById(1);
System.out.println(user);
user.setName("zhou");
user.setAge(5);
int i = userMapper.updateById(user);
}
失败:
@Test
public void versionTest (){
user user= userMapper.selectById(1);
System.out.println(user);
user.setName("zhou");
user.setAge(5);
user user2= userMapper.selectById(1);
user2.setName("zhou");
user2.setAge(6);
userMapper.updateById(user2);
userMapper.updateById(user);
}
最终结果是age=6 age=5是不会成功的
条件构造器Wrapper
介绍一个重要的方法
获取自定义SQL 简化自定义XML复杂情况
使用方法: `select xxx from table` + ${ew.customSqlSegment}
注意事项: 1. 逻辑删除需要自己拼接条件 (之前自定义也同样) 2. 不支持wrapper中附带实体的情况 (wrapper自带实体会更麻烦) 3. 用法 ${ew.customSqlSegment} (不需要where标签包裹,切记!) 4. ew是wrapper定义别名,不能使用其他的替换
public String getCustomSqlSegment() {
MergeSegments expression = getExpression();
if (Objects.nonNull(expression)) {
NormalSegmentList normal = expression.getNormal();
String sqlSegment = getSqlSegment();
if (StringUtils.isNotBlank(sqlSegment)) {
if (normal.isEmpty()) {
return sqlSegment;
} else {
return Constants.WHERE + StringPool.SPACE + sqlSegment;
}
}
}
return StringPool.EMPTY;
}
我们使用一些的复杂SQL就可以只用这个来替代
@SpringBootTest
public class WrapperTest {
@Autowired
private userMapper userMapper;
@Test
public void test01(){
QueryWrapper<user> wrapper =new QueryWrapper<>();
//注意:字段名并不是写你实体类里面的字段名称,而是写数据库里面的字段名称。
wrapper.isNotNull("create_time");
List<user> users = userMapper.selectList(wrapper);
users.forEach(System.out::println);
}
@Test
public void test02(){
QueryWrapper<user> wrapper =new QueryWrapper<>();
wrapper.like("name","L")
.ge("age",6)
.isNotNull("email");
List<user> users = userMapper.selectList(wrapper);
}
@Test
public void test03(){
QueryWrapper<user> wrapper =new QueryWrapper<>();
wrapper
.notLike("name","z")
.likeRight("email","t"); //相当于是t%
List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);
maps.forEach(System.out::println);
}
@Test
//条件子查询
public void test04(){
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);
}
}
注意test03()的查询结果是
QueryWrapper介绍
select方法
主要功能:可以选择自己需要查询的列;
@Override
public QueryWrapper<T> select(String... columns) {
if (ArrayUtils.isNotEmpty(columns)) {
this.sqlSelect.setStringValue(String.join(StringPool.COMMA, columns));
}
return typedThis;
}
Select重载形式
//第一个参数是实体类的字节码对象。第二个参数是一个函数式接口,可以通过里面test返回的Boolean值,来选择该列是否查询。
public QueryWrapper<T> select(Class<T> entityClass, Predicate<TableFieldInfo> predicate)
UpdateWrapper介绍
实列将ID大于1的用户的年龄修改为99
update
user
set
age=99
where
ID>1
UpdateWrapper<User> updateWrapper=new UpdateWrapper<>();
updateWrapper.gt("id",1);
updateWrapper.set("age",99);
userMapper.update(null,updateWrapper);
查询操作与拓展
操作:①查询一个ID②查询一组ID
@Test
public void selectById(){
//查询一个数据
user user =userMapper.selectById(1L);
System.out.println(user);
//查询多个数据
List<user> users = userMapper.selectBatchIds(Arrays.asList(1,2,3));
users.forEach(System.out::println);
}
按条件查询
简单的条件可以使用万能map来实现
@Test
public void selectBymap(){
Map<String,Object> map =new HashMap<>();
map.put("name","L");
map.put("Id",9);
List<user> users = userMapper.selectByMap(map);
users.forEach(System.out::println);
}
运行查看日志信息
复杂的添加比如大小于,或者不是查询所有字段的话就要使用Wrapper条件构造器了
分页查询
分页方法:
-
使用limit
-
使用pagehalper第三方插件
-
使用mybaits-plus分页插件
mybatis-plus分页插件的使用最新版本
再mybatis-plus的配置类中添加内置插件配置
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
return interceptor;
}
老版本使用
//分页插件
@Bean
public PaginationInterceptor paginationInterceptor(){
return new PaginationInterceptor();
}
然后就可以直接的去测试使用:
@Test
public void selectByPages(){
//第一个参数是每页几个
//当前是第几页
Page<user> page =new Page<>(1,5);
userMapper.selectPage(page,null);
page.getRecords().forEach(System.out::println);
}
多表的分页查询
自定义方法,并将自定义的方式支持分页查询。
例如:将返回值和参数使用Page。MP会自动给我添加上LIMI语句
IPage<User> findAll(Page<User>page);
删除操作及拓展
和查找操作一样有三种方式
-
通过删除一个ID deleteById();
-
通过删除一组ID deleteBatchIds(Arrays.asList(1,2,3,4))
-
通过万能的map删除deleteByMap();
逻辑删除
物理删除:在数据库中直接删除掉
逻辑删除:没有在数据中移除数据,而是通过一个变量让他失效,比如使用deleted =0 = =>deleted=1
比如回收站里面,我们将自己不需要的文件丢道到回收站里面的操作就是逻辑删除。数据时还可以恢复的
mybatis-plus逻辑删除步骤:
- 在数据库中增加一个deleted字段,表示逻辑删除的标识。官网说明
只对自动注入的 sql 起效:
插入: 不作限制
查找: 追加 where 条件过滤掉已删除数据,如果使用 wrapper.entity 生成的 where 条件也会自动追加该字段
更新: 追加 where 条件防止更新到已删除数据,如果使用 wrapper.entity 生成的 where 条件也会自动追加该字段
删除: 转变为 更新
例如:
删除: update user set deleted=1 where id = 1 and deleted=0
查找: select id,name,deleted from user where deleted=0
字段类型支持说明:
支持所有数据类型(推荐使用 Integer,Boolean,LocalDateTime)
如果数据库字段使用datetime,逻辑未删除值和已删除值支持配置为字符串null,另一个值支持配置为函数来获取值如now()
附录:
逻辑删除是为了方便数据恢复和保护数据本身价值等等的一种方案,但实际就是删除。
如果你需要频繁查出来看就不应使用逻辑删除,而是以一个状态去表示。
![image-20230613121015768](C:%5CUsers%5Cpc%5CAppData%5CRoaming%5CTypora%5Ctypora-user-images%5Cimage-20230613121015768.png)
- 在yml文件中配置相关的配置
```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)
-
再在实体类中同步字段,并在deleted字段上标明逻辑字段的注释
@TableLogic //逻辑删除注解 private Integer deleted;
自定义方法
在原来mybatis
User findone(String mail);
使用mybatis-plus
User findone(@Param(Constants.WRAPPER) Wrapper<User> queryWrapper);
XML
<select id="findone" resultType="com.zl.note.pojo.User">
select * from z_user ${ew.customSqlSegment}
</select>
注意这里使用${}
,因为如果使用#{}是不会预编译的,但是ew.customSqlSegment里面是where条件等语句是需要预编译的。
Service接口
MP也为我们提供了Serviqe层的实现。我们只需要编写一个接口,继承IService
,并创建一个接口实现类继承serviceImpl,即可使用。
相比于Mapper接口,Service层主要是支持了更多批量操作的方法。
Service改造
public interface UserService extends IService<User>
serviceImp改造
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService
ServiceImpl提供了一系列的方法
自定义方法
那么我们需要注入Mapper对象吗,其实MP里面存在一个方法getBaseMapper
就可以获得响应的Mapper对象。
代码自动生成器(重点)
导入依赖
<!--mybatis-plus 依赖-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3.4</version>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.1</version>
</dependency>
<!--freemarker 依赖-->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.31</version>
</dependency>
方法实体类
方法一:将所有的配置提前全部写好
package com.zhoulei.mybatis_plus01;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.IFill;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.OutputFile;
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.DbColumnType;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import com.baomidou.mybatisplus.generator.fill.Column;
import com.baomidou.mybatisplus.generator.fill.Property;
import java.sql.Types;
import java.util.Collections;
import static com.baomidou.mybatisplus.generator.config.GlobalConfig.*;
public class Autobuild {
public static void main(String[] args) {
String outurl="/mybatis_plus01";
System.out.println((System.getProperty("user.dir")+outurl+"/src/main/java"));
FastAutoGenerator.create("jdbc:mysql://localhost:3306/mybatis_plus?useSSL=false&serverTimezone=GMT%2B8",
"root",
"123456"
)
//配置全局变量
.globalConfig((Builder builder) -> {
builder.author("zl") // 设置作者
.enableSwagger() // 开启 swagger 模式
.disableOpenDir() //禁止打开windows资源管理器
.dateType(DateType.ONLY_DATE)//日期类型
.fileOverride()//开启覆盖之前生成的文件
// .fileOverride()//覆盖已经生成的文件
.outputDir(System.getProperty("user.dir")+outurl+"/src/main/java"); // 指定输出目录 将生成的代码就会生成到指定的路径下面
})
//包配置
.packageConfig((PackageConfig.Builder builder) -> {
builder.parent("com.zhoulei.mybatis_plus01") // 设置父包名,在那个包下面生成代码
.moduleName("blog") // 设置父包模块名
.entity("pojo") //配置pojo包 实体类包的名称
.mapper("mapper") //mapper dao 层的名称
.controller("controller") //配置controller层名称
.service("service")//配置servicec层的名称
.serviceImpl("serviceImpl")
.xml("mapper")
.pathInfo(Collections.singletonMap(OutputFile.mapperXml, System.getProperty("user.dir")+outurl+"/src/main/resources/mapper")); // 设置mapperXml生成路径
})
//策略设置
.strategyConfig((StrategyConfig.Builder builder) -> {
builder.addInclude("user") // 设置需要映射数据库的表名,这个需要的参数是一 Set<String> include;可以是多个表
.addTablePrefix("t_", "c_") // 设置过滤表前缀
.entityBuilder() //它用于配置实体类的构建器 EntityBuilder,从而定制实体类的生成策略
.enableLombok()//lombok生成
.logicDeleteColumnName("deleted") //设置逻辑删除的字段名
.versionColumnName("version")//设置乐观锁的字段名
.addTableFills(new Column("create_time", FieldFill.INSERT) )//添加自动填充,比如插入时间
.addTableFills(new Property("updateTime",FieldFill.UPDATE))//添加自动填充,比如更新时间
//两种方式一个是通过数据库的表名创建,另一个是通过实体类属性来创建
// .addTableFills(new Property("createTime", FieldFill.INSERT) )//添加自动填充,比如插入时间
// .addTableFills(new Column("update_time",FieldFill.UPDATE))//添加自动填充,比如更新时间
.idType(IdType.ASSIGN_ID)
.mapperBuilder()
.superClass(BaseMapper.class)
.enableBaseResultMap()//基础map映射
.enableBaseColumnList()//基础行列表映射
.formatMapperFileName("%sMapper")
.enableMapperAnnotation()
.formatXmlFileName("%sMapper")
.serviceBuilder()
.formatServiceFileName("%sService")
.formatServiceImplFileName("%sServiceImpl")
.controllerBuilder()
.formatFileName("%sController")
.enableRestStyle();
;
}).templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
.execute();
}
}
//方法二:使用交互式
package com.zhoulei.mybatis_plus01;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.OutputFile;
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.engine.FreemarkerTemplateEngine;
import com.baomidou.mybatisplus.generator.fill.Column;
import com.baomidou.mybatisplus.generator.fill.Property;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.*;
import java.util.stream.Collectors;
@SpringBootTest
public class UserGenerator {
public static void main(String[] args) {
String property = System.getProperty("user.dir");//获取目录路径
String database = getDatabase(); //数据库名称;
String username= getUsername();//数据库用户名
String password=getPassword();//数据库密码
String outurl=getOuturl();//输出路径
String author=getAuthor();//获取作者
List <String> tables= getTables();//表名集合
String mapperXml =getMapperXML();//mapperXml生成路径
String prefix = gettablePrefix();//表的前缀名
String parent =getParent();//父包名
String moduelName=getmoduelName();//模块名
FastAutoGenerator.create("jdbc:mysql://localhost:3306/"+database+"?useSSL=false&serverTimezone=GMT%2B8",
username,
password
)
//配置全局变量
.globalConfig((GlobalConfig.Builder builder) -> {
builder.author(author) // 设置作者
.enableSwagger() // 开启 swagger 模式
.disableOpenDir() //禁止打开windows资源管理器
.dateType(DateType.ONLY_DATE)//日期类型
.fileOverride()//开启覆盖之前生成的文件
// .fileOverride()//覆盖已经生成的文件
.outputDir(property+outurl+"/src/main/java"); // 指定输出目录 将生成的代码就会生成到指定的路径下面
})
//包配置
.packageConfig((PackageConfig.Builder builder) -> {
builder.parent(parent) // 设置父包名,在那个包下面生成代码
.moduleName(moduelName) // 设置父包模块名
.entity("pojo") //配置pojo包 实体类包的名称
.mapper("mapper") //mapper dao 层的名称
.controller("controller") //配置controller层名称
.service("service")//配置servicec层的名称
.serviceImpl("serviceImpl")
.xml("mapper")
.pathInfo(Collections.singletonMap(OutputFile.mapperXml, System.getProperty("user.dir")+outurl+"/src/main/"+mapperXml)); // 设置mapperXml生成路径
})
//策略设置
.strategyConfig((StrategyConfig.Builder builder) -> {
builder.addInclude(tables) // 设置需要映射数据库的表名,这个需要的参数是一 Set<String> include;可以是多个表
.addTablePrefix(prefix) // 设置过滤表前缀
.entityBuilder() //它用于配置实体类的构建器 EntityBuilder,从而定制实体类的生成策略
.enableLombok()//lombok生成
.logicDeleteColumnName("deleted") //设置逻辑删除的字段名
.versionColumnName("version")//设置乐观锁的字段名
.addTableFills(new Column("create_time", FieldFill.INSERT) )//添加自动填充,比如插入时间
.addTableFills(new Property("updateTime",FieldFill.UPDATE))//添加自动填充,比如更新时间
//两种方式一个是通过数据库的表名创建,另一个是通过实体类属性来创建
// .addTableFills(new Property("createTime", FieldFill.INSERT) )//添加自动填充,比如插入时间
// .addTableFills(new Column("update_time",FieldFill.UPDATE))//添加自动填充,比如更新时间
.idType(IdType.ASSIGN_ID)
.mapperBuilder()
.superClass(BaseMapper.class)
.enableBaseResultMap()//基础map映射
.enableBaseColumnList()//基础行列表映射
.formatMapperFileName("%sMapper")
.enableMapperAnnotation()
.formatXmlFileName("%sMapper")
.serviceBuilder()
.formatServiceFileName("%sService")
.formatServiceImplFileName("%sServiceImpl")
.controllerBuilder()
.formatFileName("%sController")
.enableRestStyle();
;
}).templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
.execute();
}
//输入数据库名称
public static String getDatabase() {
Scanner sc = new Scanner(System.in);
System.out.println("输入数据库名称");
return sc.next();
}
//输入数据库用户名
public static String getUsername() {
Scanner sc = new Scanner(System.in);
System.out.println("输入数据库用户名");
return sc.next();
}
//输入数据库密码
public static String getPassword() {
Scanner sc = new Scanner(System.in);
System.out.println("输入数据库密码");
return sc.next();
}
//输入输出路径
public static String getOuturl() {
Scanner sc = new Scanner(System.in);
System.out.println("请输入生成文件输入路径,建议输入项目根目录到src目录的距离");
System.out.println("例如我当前总项目叫【project】那么我输入【/hy-generator】那么我输出路径为为【/hy-generator/src/main/java】");
String outurl = sc.next();
if (outurl.trim().equals("")) {
outurl = "/";
}
return outurl;
}
//输入作者
public static String getAuthor() {
Scanner sc = new Scanner(System.in);
System.out.println("输入作者");
return sc.next();
}
//输入表名
public static List <String> getTables() {
Scanner sc = new Scanner(System.in);
List<String> tables = new ArrayList<>();
System.out.println("你可以输入一个或这是多个表名,但是要以','分隔开,并且以'$'标识结束");
while (sc.hasNext()) {
String table = sc.next();
if(table.equals("$")){
return tables;
}
String[] split = table.split(",");
for (int i = 0; i < split.length; i++) {
tables.add(split[i]);
}
}
return tables;
}
//输入mapperXml生成路径
public static String getMapperXML() {
Scanner sc = new Scanner(System.in);
System.out.println("mapperXml生成路径");
System.out.println("比如是在/src/main/java/resources/mapper,就输入/resources/mapper");
return sc.next();
}
//表前缀输入
private static String gettablePrefix() {
System.out.println("请输入表前缀");
System.out.println("例如我数据库表叫【t_admin】那么我输入【t_】那么我的实体类名为【Admin】");
Scanner scanner = new Scanner(System.in);
String tablePrefix = scanner.next();
System.out.println("你输入的表前缀是:" + tablePrefix);
return tablePrefix;
}
//输入父包名
private static String getParent() {
System.out.println("请输入父包名");
System.out.println("例如我的父包名是com.zl.mybatis_plus01,那写service,dao,controller层都会生成在该报下");
Scanner sc = new Scanner(System.in);
return sc.next();
}
//输入moduelName名
private static String getmoduelName() {
System.out.println("请输入moduelName");
Scanner sc = new Scanner(System.in);
return sc.next();
}
}
- mybatis-plus mybatis plusmybatis-plus mybatis-plus mybatis plus mybatis-plus springboot mybatis mapper mybatis-plus springboot mybatis plus mybatis-plus mybatisplus mybatis java mybatis-plus mybatis spring java mapper-locations mapperlocations mybatis-plus mybatis-plus typehandler mybatis类型 mybatis-plus语句mybatis日志 mybatis-plus实体mybatis时间