目录
MyBatis-Plus 是一个基于 MyBatis 的增强工具,旨在简化 MyBatis 的使用并提供更好的性能和灵活性。官方网站为:MyBatis-Plus
一、依赖包
<!--mybatis-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3</version>
</dependency>
<!--mybatisplus自动生成代码依赖-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency>
<!--mysql依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
二、配置文件
#设置项目mapper目录(dao包路径)的日志级别为DEBUG
level:
com:
xxx:
xxx
xxx: DEBUG
mybatis-plus:
# mapper文件地址
mapper-locations: classpath*:com/backup/mysqlbackup/mapper/**/*.xml
#不想打印 SQL 日志
#configuration:
# log-impl: org.apache.ibatis.logging.nologging.NoLoggingImpl
global-config:
db-config:
#设置被删除逻辑字段,1标识删除,0标识未删除
logic-delete-field: status
logic-delete-value: 1
logic-not-delete-value: 0
三、配置类
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MybatisPlusConfig {
/**
* 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题(该属性会在旧插件移除后一同移除)
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
paginationInnerInterceptor.setDbType(DbType.MYSQL);
paginationInnerInterceptor.setOverflow(true);
interceptor.addInnerInterceptor(paginationInnerInterceptor);
return interceptor;
}
/**
* 设置自动注入规则
*/
@Bean
public MetaObjectHandler metaObjectHandler(){
return new MyMetaObjectHandler();
}
}
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import java.util.Date;
/**
* mybatis-plus 自定义公共字段填充处理器
*/
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
this.strictInsertFill(metaObject, "createTime", Date.class, new Date());
}
@Override
public void updateFill(MetaObject metaObject) {
this.strictUpdateFill(metaObject, "createTime", Date.class, new Date());
}
}
四、代码生成器模板
package ${package.Entity};
<#list table.importPackages as pkg>
import ${pkg};
</#list>
<#if table.convert>
import com.baomidou.mybatisplus.annotation.TableName;
</#if>
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
<#if entityLombokModel>
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
</#if>
/**
* <p>
* ${table.comment!}
* </p>
*
* @author ${author}
* @since ${date}
*/
<#if entityLombokModel>
@Data
</#if>
<#if table.convert>
@TableName("${table.name}")
</#if>
@ApiModel(value = "${entity}对象", description = "${table.comment!}")
<#if superEntityClass??>
public class ${entity} extends ${superEntityClass}<#if activeRecord><${entity}></#if> {
<#elseif activeRecord>
public class ${entity} extends Model<${entity}> {
<#else>
public class ${entity} implements Serializable {
</#if>
private static final long serialVersionUID = 1L;
<#-- ---------- BEGIN 字段循环遍历 ---------->
<#list table.fields as field>
<#if field.keyFlag>
<#assign keyPropertyName="${field.propertyName}"/>
</#if>
<#if field.comment!?length gt 0>
//${field.comment}
@ApiModelProperty(value = "${field.comment}")
</#if>
<#if field.keyFlag>
<#-- 主键 -->
<#if field.keyIdentityFlag>
@TableId(value = "${field.name}", type = IdType.AUTO)
<#elseif idType??>
@TableId(value = "${field.name}", type = IdType.${idType})
<#elseif field.convert>
@TableId("${field.name}")
</#if>
<#-- 普通字段 -->
<#elseif field.fill??>
<#-- ----- 存在字段填充设置 ----->
<#if field.convert>
@TableField(value = "${field.name}", fill = FieldFill.${field.fill})
<#else>
@TableField(fill = FieldFill.${field.fill})
</#if>
<#elseif field.convert>
@TableField("${field.name}")
</#if>
<#-- 乐观锁注解 -->
<#if (versionFieldName!"") == field.name>
@Version
</#if>
<#-- 逻辑删除注解 -->
<#if (logicDeleteFieldName!"") == field.name>
@TableLogic
</#if>
private ${field.propertyType} ${field.propertyName};
</#list>
<#------------ END 字段循环遍历 ---------->
<#if !entityLombokModel>
<#list table.fields as field>
<#if field.propertyType == "boolean">
<#assign getprefix="is"/>
<#else>
<#assign getprefix="get"/>
</#if>
public ${field.propertyType} ${getprefix}${field.capitalName}() {
return ${field.propertyName};
}
<#if entityBuilderModel>
public ${entity} set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
<#else>
public void set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
</#if>
this.${field.propertyName} = ${field.propertyName};
<#if entityBuilderModel>
return this;
</#if>
}
</#list>
</#if>
<#if entityColumnConstant>
<#list table.fields as field>
public static final String ${field.name?upper_case} = "${field.name}";
</#list>
</#if>
<#if activeRecord>
@Override
protected Serializable pkVal() {
<#if keyPropertyName??>
return this.${keyPropertyName};
<#else>
return null;
</#if>
}
</#if>
<#if !entityLombokModel>
@Override
public String toString() {
return "${entity}{" +
<#list table.fields as field>
<#if field_index==0>
"${field.propertyName}=" + ${field.propertyName} +
<#else>
", ${field.propertyName}=" + ${field.propertyName} +
</#if>
</#list>
"}";
}
</#if>
}
<?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="${package.Mapper}.${table.mapperName}">
<#if enableCache>
<!-- 开启二级缓存 -->
<cache type="org.mybatis.caches.ehcache.LoggingEhcache"/>
</#if>
<#if baseResultMap>
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="${package.Entity}.${entity}">
<#list table.fields as field>
<#if field.keyFlag><#--生成主键排在第一位-->
<id column="${field.name}" property="${field.propertyName}" />
</#if>
</#list>
<#list table.commonFields as field><#--生成公共字段 -->
<result column="${field.name}" property="${field.propertyName}" />
</#list>
<#list table.fields as field>
<#if !field.keyFlag><#--生成普通字段 -->
<result column="${field.name}" property="${field.propertyName}" />
</#if>
</#list>
</resultMap>
</#if>
<#if baseColumnList>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
<#list table.commonFields as field>
${field.name},
</#list>
${table.fieldNames}
</sql>
</#if>
</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="${package.Mapper}.${table.mapperName}">
<#if enableCache>
<!-- 开启二级缓存 -->
<cache type="org.mybatis.caches.ehcache.LoggingEhcache"/>
</#if>
<#if baseResultMap>
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="${package.Entity}.${entity}">
<#list table.fields as field>
<#if field.keyFlag><#--生成主键排在第一位-->
<id column="${field.name}" property="${field.propertyName}" />
</#if>
</#list>
<#list table.commonFields as field><#--生成公共字段 -->
<result column="${field.name}" property="${field.propertyName}" />
</#list>
<#list table.fields as field>
<#if !field.keyFlag><#--生成普通字段 -->
<result column="${field.name}" property="${field.propertyName}" />
</#if>
</#list>
</resultMap>
</#if>
<#if baseColumnList>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
<#list table.commonFields as field>
${field.name},
</#list>
${table.fieldNames}
</sql>
</#if>
</mapper>
package ${package.Service};
import ${package.Entity}.${entity};
import ${superServiceClassPackage};
/**
* <p>
* ${table.comment!} 服务类
* </p>
*
* @author ${author}
* @since ${date}
*/
<#if kotlin>
interface ${table.serviceName} : ${superServiceClass}<${entity}>
<#else>
public interface ${table.serviceName} extends ${superServiceClass}<${entity}> {
}
</#if>
package ${package.ServiceImpl};
import ${package.Entity}.${entity};
import ${package.Mapper}.${table.mapperName};
import ${package.Service}.${table.serviceName};
import ${superServiceImplClassPackage};
import org.springframework.stereotype.Service;
/**
* <p>
* ${table.comment!} 服务实现类
* </p>
*
* @author ${author}
* @since ${date}
*/
@Service
<#if kotlin>
open class ${table.serviceImplName} : ${superServiceImplClass}<${table.mapperName}, ${entity}>(), ${table.serviceName} {
}
<#else>
public class ${table.serviceImplName} extends ${superServiceImplClass}<${table.mapperName}, ${entity}> implements ${table.serviceName} {
}
</#if>
package ${package.Controller};
import ${package.Entity}.${entity};
import ${package.Service}.${table.serviceName};
import 自定义公共返回响应类.Result;
import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
<#if restControllerStyle>
<#else>
import org.springframework.stereotype.Controller;
</#if>
<#if superControllerClassPackage??>
import ${superControllerClassPackage};
</#if>
import java.util.List;
/**
* <p>
* ${table.comment} 前端控制器
* </p>
*
* @author ${author}
* @since ${date}
*/
@Api(tags = "${table.comment}")
<#if restControllerStyle>
@RestController
<#else>
@Controller
</#if>
@RequestMapping("<#if package.ModuleName??>/${package.ModuleName}</#if><#if controllerMappingHyphenStyle??>${controllerMappingHyphen}<#else>${table.entityPath}</#if>")
<#if kotlin>
class ${table.controllerName}<#if superControllerClass??> : ${superControllerClass}()</#if>
<#else>
<#if superControllerClass??>
public class ${table.controllerName} extends ${superControllerClass} {
<#else>
public class ${table.controllerName} {
</#if>
@Autowired
private ${table.serviceName} ${table.serviceName?uncap_first};
@ApiOperation(value = "${table.comment}分页列表", response = ${entity}.class)
@GetMapping(value = "/page")
public Result list(${entity} ${table.entityPath}, @ApiParam("当前页码")@RequestParam("pageNum")Long pageNum,@ApiParam("每页显示条目个数") @RequestParam("pageSize")Long pageSize) {
QueryWrapper<${entity}> queryWrapper= new QueryWrapper<>(${table.entityPath});
IPage<${entity}> page = ${table.entityPath}Service.page(
new Page<>(pageNum, pageSize),queryWrapper );
return Result.success("查询成功",page);
}
@ApiOperation(value = "${table.comment}条件查询")
@PostMapping("/get")
public Result list(@RequestBody ${entity} ${table.entityPath}){
QueryWrapper<${entity}> queryWrapper= new QueryWrapper<>(${table.entityPath});
List<${entity}> ${table.entityPath}List = ${table.entityPath}Service.list(queryWrapper);
return Result.success("查询成功",${table.entityPath}List);
}
@ApiOperation(value = "${table.comment}详情", response = ${entity}.class)
@GetMapping(value = "/info/{id}")
public Result info(@PathVariable Long id) {
${entity} data = ${table.serviceName?uncap_first}.getById(id);
return Result.success("查询成功",data);
}
@ApiOperation(value = "${table.comment}新增")
@PostMapping(value = "/add")
public Result add(@RequestBody ${entity} ${table.entityPath}) {
${table.entityPath}Service.save(${table.entityPath});
return Result.success("保存成功");
}
@ApiOperation(value = "${table.comment}根据id修改")
@PostMapping(value = "/modify")
public Result modify(@RequestBody ${entity} ${table.entityPath}) {
${table.entityPath}Service.updateById(${table.entityPath});
return Result.success("更新成功");
}
@ApiOperation(value = "${table.comment}根据id删除")
@GetMapping(value = "/remove/{id}")
public Result remove(@PathVariable("id") Long id) {
${table.entityPath}Service.removeById(id);
return Result.success();
}
@ApiOperation(value = "${table.comment}根据id批量删除")
@PostMapping(value = "/removes")
public Result removes(@RequestBody List<Long> ids) {
${table.serviceName?uncap_first}.removeByIds(ids);
return Result.success();
}
}
</#if>
五、代码生成工具类
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* @Description:MP代码生成器
**/
public class CodeGenerator {
static final String URL = "数据库地址";
public static void main(String[] args) {
String projectPath = System.getProperty("user.dir");//获取项目路径
FastAutoGenerator.create(URL, "数据库账号", "数据库密码")
//全局配置
.globalConfig((scanner, builder) -> {
builder.author("author")
.dateType(DateType.ONLY_DATE) //设置日期格式为Date
.outputDir(projectPath + "/src/main/java")//输出路径
.enableSwagger()//开启swagger3
.fileOverride()//覆盖文件
.disableOpenDir();//不打开文件夹
})
//包名配置
.packageConfig((scanner, builder) -> {
builder.parent("输出包名")
.service("service")
.serviceImpl("service.impl")
.controller("controller")
.entity("entity")
.mapper("mapper");
})
//策略配置
.strategyConfig((scanner, builder) -> {
builder.addInclude(getTables(scanner.apply("请输入表名,多个英文逗号分隔?所有输入 all")))
.addTablePrefix("t_")//表前缀
.serviceBuilder().formatServiceFileName("%sService")//去掉Service的 "I" 前缀
.controllerBuilder().enableRestStyle()//restful开启
.enableHyphenStyle()//url改变 例如:index_id_1
.entityBuilder().enableLombok();
})
// 模板配置
.templateConfig((scanner, builder) -> {
builder.disable(TemplateType.ENTITY)
.entity("/模板路径/entity.java")
.service("/模板路径/service.java")
.serviceImpl("/模板路径/serviceImpl.java")
.mapper("/模板路径/mapper.java")
.xml("/模板路径/mapper.xml")
.controller("/模板路径/controller.java")
.build();})
.templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
//执行
.execute();
}
// 处理 all 情况
protected static List<String> getTables(String tables) {
return "all".equals(tables) ? Collections.emptyList() : Arrays.asList(tables.split(","));
}
}
resource目录下如果模板读取不到的情况下在pom.xml加如下配置
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.ftl</include>
</includes>
</resource>
</resources>
</build>
六、注解
@TableLogic 注解将会在 select 语句的 where 条件添加条件,过滤掉已删除数据
且使用 wrapper.entity 生成的 where 条件会忽略该字段
SELECT user_id,name,sex,age,deleted FROM user WHERE user_id=1 AND deleted='0'
@TableLogic 注解将会在 update 语句的 where 条件后追加条件,防止更新到已删除数据
且使用 wrapper.entity 生成的 where条件会忽略该字段
update user set deleted=1 where id = 1 and deleted=0
@TableLogic 注解会将 delete 语句转变为 update 语句
update user set deleted=1 where id = 1 and deleted=0
支持所有数据类型(推荐使用 Integer、Boolean、LocalDateTime)
如果数据库字段使用 datetime,逻辑未删除值和已删除值支持配置为字符串 null,另一个值支持配置为函数来获取值如now()
(1)逻辑删除是为了方便数据恢复和保护数据本身价值等等的一种方案,但实际就是删除。
(2)如果你需要频繁查出来看就不应使用逻辑删除,而是以一个状态去表示。