一、代码生成
1.添加依赖
com.baomidou
mybatis-plus-boot-starter
3.5.3.1
com.github.yulichang
mybatis-plus-join-boot-starter
1.4.6
org.apache.velocity
velocity-engine-core
2.3
2.创建配置文件/resources/mybatis-generator.properties
#设置作者
author=Maye
#数据源
jdbc.username=root
jdbc.password=000111
jdbc.url=jdbc:postgresql://10.1.0.12:55432/wflow_pro?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull
#模块名
module=szh-services/szh-big-event-service
#数据库表名(此处切不可为空,如果为空,则默认读取数据库的所有表名,多个表用逗号隔开)
tableNames=szh_be_event_record_file
#自定义包路径
parent=cn.shenzhihe.event
3.添加模板位置/resources/templates
templates.zip.bat
4.生成代码MybatisGenerator.java
package cn.shenzhihe.event.utils;
import com.baomidou.mybatisplus.annotation.IdType;
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 lombok.extern.slf4j.Slf4j;
import java.util.Collections;
import java.util.ResourceBundle;
/**
* Mybatis Plus生成公爵
* @author: Maye
* @since: 2023-07-03
* @description: 应急任务公共方法
*/
@Slf4j
public class MybatisGenerator {
public static void main(String[] args) {
ResourceBundle rb = ResourceBundle.getBundle("mybatis-generator");
String module = rb.getString("module");
//项目根目录 不可修改
String projectPath = System.getProperty("user.dir") + "/" + module;
String url = rb.getString("jdbc.url");
String username = rb.getString("jdbc.username");
String password = rb.getString("jdbc.password");
// 1.数据源配置
DataSourceConfig dsc = new DataSourceConfig.Builder(url, username, password).build();
//通过datasourceConfig创建AutoGenerator
AutoGenerator generator = new AutoGenerator(dsc);
/*
全局配置
*/
String filePath = projectPath + "/src/main/java"; //java下的文件路径
GlobalConfig global = new GlobalConfig.Builder()
.outputDir(filePath)//生成的输出路径
.author(rb.getString("author"))//生成的作者名字
.enableSwagger() //开启swagger,需要添加swagger依赖并配置
.dateType(DateType.TIME_PACK)//时间策略
.commentDate("yyyy-MM-dd")//格式化时间格式
.disableOpenDir()//禁止打开输出目录,默认false
.fileOverride()//覆盖生成文件
.build();
/*
* 包配置
*/
PackageConfig packages = new PackageConfig.Builder()
.entity("model.entity")//实体类包名
.parent(rb.getString("parent"))//父包名。如果为空,将下面子包名必须写全部, 否则就只需写子包名
.controller("controller")//控制层包名
.mapper("mapper")//mapper层包名
.xml("mapper.xml")//数据访问层xml包名
.service("service")//service层包名
.serviceImpl("service.impl")//service实现类包名
.pathInfo(Collections.singletonMap(OutputFile.xml, projectPath + "/src/main/resources/mapper")) //路径配置信息,就是配置各个文件模板的路径信息,这里以mapper.xml为例
.build();
/*
* 模板配置
*/
TemplateConfig template = new TemplateConfig.Builder()
.entity("/templates/entity.java.vm")
.service("/templates/service.java.vm")
.serviceImpl("/templates/serviceImpl.java.vm")
.mapper("/templates/mapper.java.vm")
.controller("/templates/controller.java")
.build();
String[] tableNames = rb.getString("tableNames").split(",");
/*
* 策略配置开始
*/
StrategyConfig strategyConfig = new StrategyConfig.Builder()
//.enableCapitalMode()//开启全局大写命名
//.likeTable()模糊表匹配
.addInclude(tableNames)//添加表匹配,指定要生成的数据表名,不写默认选定数据库所有表
//.disableSqlFilter()禁用sql过滤:默认(不使用该方法)true
//.enableSchema()启用schema:默认false
.entityBuilder() //实体策略配置
//.disableSerialVersionUID()禁用生成SerialVersionUID:默认true
.enableChainModel()//开启链式模型
.enableLombok()//开启lombok
.enableRemoveIsPrefix()//开启 Boolean 类型字段移除 is 前缀
.enableTableFieldAnnotation()//开启生成实体时生成字段注解
//.addTableFills()添加表字段填充
.naming(NamingStrategy.underline_to_camel)//数据表映射实体命名策略:默认下划线转驼峰underline_to_camel
.columnNaming(NamingStrategy.underline_to_camel)//表字段映射实体属性命名规则:默认null,不指定按照naming执行
.idType(IdType.AUTO)//添加全局主键类型
.formatFileName("%s")//格式化实体名称,%s取消首字母I
.enableFileOverride()
.build()
.mapperBuilder()//mapper文件策略
.enableFileOverride()
.enableMapperAnnotation()//开启mapper注解
.enableBaseResultMap()//启用xml文件中的BaseResultMap 生成
.enableBaseColumnList()//启用xml文件中的BaseColumnList
//.cache(缓存类.class)设置缓存实现类
.formatMapperFileName("%sMapper")//格式化Dao类名称
.formatXmlFileName("%sMapper")//格式化xml文件名称
.build()
.serviceBuilder()//service文件策略
.enableFileOverride()
.formatServiceFileName("%sService")//格式化 service 接口文件名称
.formatServiceImplFileName("%sServiceImpl")//格式化 service 接口文件名称
.build()
.controllerBuilder() //控制层策略
.enableHyphenStyle() //开启驼峰转连字符,默认:false
.enableRestStyle()//开启生成@RestController
.formatFileName("%sController")//格式化文件名称
.enableFileOverride()
.build();
/*
* 将所有配置项整合到AutoGenerator中进行执行
*/
generator.global(global)
.template(template)
.global(global)
// .injection(injectionConfig)
.packageInfo(packages)
.strategy(strategyConfig)
.execute();
}
}
二、常用配置
1.自动添加创建人、更新人、创建时间、更新时间
package cn.shenzhihe.event.config;
import cn.shenzhihe.base.common.SpringContextUtil;
import cn.shenzhihe.base.common.constants.Constants;
import cn.shenzhihe.event.utils.UserUtil;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
/**
* @author: Maye
* @since: 2023-07-03
* @description: Mybatis plus 扩展类
*/
@Component
public class EventMetaObjectHandler implements MetaObjectHandler {
/**
* mybatis 插入数据库自动写入createTime、creator
*
* @param metaObject 元对象
*/
@Override
public void insertFill(MetaObject metaObject) {
this.setFieldValByName("createTime", LocalDateTime.now(), metaObject);
this.setFieldValByName("creator", UserUtil.getLoginUserId(), metaObject);
}
/**
* mybatis 更新数据库自动写入updateTime、updater
*
* @param metaObject 元对象
*/
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject);
this.setFieldValByName("updater", UserUtil.getLoginUserId(), metaObject);
}
}
2.拦截器(租户处理、数据库方言)
package cn.shenzhihe.event.config;
import cn.shenzhihe.base.common.SpringContextUtil;
import cn.shenzhihe.base.common.constants.Constants;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.StringValue;
import org.apache.ibatis.annotations.Mapper;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* MyBaits 配置类
*/
@Configuration
@MapperScan(value = "cn.shenzhihe", annotationClass = Mapper.class,
lazyInitialization = "${mybatis.lazy-initialization:false}") // Mapper 懒加载,目前仅用于单元测试
public class MybatisConfiguration {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 如果用了分页插件注意先 add TenantLineInnerInterceptor 再 add PaginationInnerInterceptor
// 用了分页插件必须设置 MybatisConfiguration#useDeprecatedExecutor = false
// interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
//task_source_key(所属演习)作为租户的字段
interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(new TenantLineHandler() {
@Override
public Expression getTenantId() {
return new StringValue(SpringContextUtil.getRequest().getHeader(Constants.SOURCE_HEADER));
}
@Override
public String getTenantIdColumn() {
return "source_key";
}
}));
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.POSTGRE_SQL));
return interceptor;
}
/**
* 自定义批量插入 SQL 注入器
*/
@Bean
public InsertBatchSqlInjector insertBatchSqlInjector() {
return new InsertBatchSqlInjector();
}
}
3.添加自定义方法
package cn.shenzhihe.event.config;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.extension.injector.methods.InsertBatchSomeColumn;
import java.util.List;
public class InsertBatchSqlInjector extends DefaultSqlInjector {
@Override
public List getMethodList(Class> mapperClass, TableInfo tableInfo) {
// super.getMethodList() 保留 Mybatis Plus 自带的方法
List methodList = super.getMethodList(mapperClass, tableInfo);
// 添加自定义方法:批量插入,方法名为 insertBatchSomeColumn
methodList.add(new InsertBatchSomeColumn());
return methodList;
}
}
4.Join联表查询
/**
* 根据类型查询列表
*
* @param type 查看EventTypeEnum.class
* @return 列表
*/
@Override
public List queryEventList(String type) {
MPJLambdaWrapper szhBeEventRecordFileVOMPJLambdaWrapper = getSzhBeEventRecordFileVOMPJLambdaWrapper().eq(SzhBeEventRecord::getType, type)
.orderBy(true, true, SzhBeEventRecord::getSortOrder, SzhBeEventRecord::getCreateTime);
;
return szhBeEventRecordMapper.selectJoinList(SzhBeEventRecordFileVO.class, szhBeEventRecordFileVOMPJLambdaWrapper);
}
private MPJLambdaWrapper getSzhBeEventRecordFileVOMPJLambdaWrapper() {
return new MPJLambdaWrapper()
//查询表1的全部字段
.selectAll(SzhBeEventRecord.class)
//查询表2的全部字段
.selectCollection(SzhBeEventRecordFile.class, SzhBeEventRecordFileVO::getSzhFiles)
//左查询表2条件 为表1的productId = 表2的id
.leftJoin(SzhBeEventRecordFile.class, SzhBeEventRecordFile::getEventRecordId, SzhBeEventRecord::getId);
}
5.分页查询
package cn.shenzhihe.base.common.pojo;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.sql.SqlInjectionUtils;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
@Schema(description = "分页参数")
@Data
public class PageParam implements Serializable {
private static final Long CURRENT_PAGE = 1L;
private static final Long PAGE_SIZE = 10L;
@Schema(description = "页码,从 1 开始", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "页码不能为空")
@Min(value = 1, message = "页码最小值为 1")
private Long pageNo = CURRENT_PAGE;
@Schema(description = "每页条数,最大值为 100", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
@NotNull(message = "每页条数不能为空")
@Min(value = 1, message = "每页条数最小值为 1")
@Max(value = 100, message = "每页条数最大值为 100")
private Long pageSize = PAGE_SIZE;
/**
* 顺序 - 升序
*/
public static final String ORDER_ASC = "asc";
/**
* 顺序 - 降序
*/
public static final String ORDER_DESC = "desc";
@Schema(description = "排序字段多字段逗号分割", requiredMode = Schema.RequiredMode.REQUIRED, example = "type")
private String fields;
@Schema(description = "排序类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "desc")
private String order;
public void setFields(String fields) {
服务器托管网 if (fields == null) {
return;
}
if (!SqlInjectionUtils.check(fields)) {
fields = "id";
}
StringBuilder fieldTemp = new StringBuilder();
for (String field : fields.split(",")) {
if (fieldTemp.length() != 0) {
fieldTemp.append(",");
}
fieldTemp.append(StrUtil.toSymbolCase(field, '_'));
}
this.fields = fieldTemp.toString();
}
}
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
/**
* 分页查询,可根据类型和标题查询
*
* @param pageParam 分页信息
* @param szhBeEventRecord 条件
* @return 结果
*/
@Override
public Page selectPage(PageParam pageParam, SzhBeEventRecord szhBeEventRecord) {
LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper();
if (EventTypeEnum.EMERGENCY_RECORD.getType().equals(szhBeEventRecord.getType())) {
lambdaQueryWrapper = lambdaQueryWrapper.eq(SzhBeEventRecord::getCreator, UserUtil.getLoginUserId());
}
if (StringUtils.isNotBlank(szhBeEventRecord.getTitle())) {
lambdaQueryWrapper = lambdaQueryWrapper.like(SzhBeEventRecord::getTitle, szhBeEventRecord.getTitle());
}
if (StringUtils.isNotBlank(szhBeEventRecord.getType())) {
lambdaQueryWrapper = lambdaQueryWrapper.like(SzhBeEventRecord::getType, szhBeEventRecord.getType());
服务器托管网 }
return szhBeEventRecordMapper.selectPage(MyBatisUtils.buildPage(pageParam), lambdaQueryWrapper);
}
package cn.shenzhihe.datarecord.utils;
import cn.hutool.core.collection.CollectionUtil;
import cn.shenzhihe.datarecord.model.pojo.PageParam;
import cn.shenzhihe.datarecord.model.pojo.SortingField;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import net.sf.jsqlparser.expression.Alias;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* MyBatis 工具类
*/
public class MyBatisUtils {
private static final String MYSQL_ESCAPE_CHARACTER = "`";
public static Page buildPage(PageParam pageParam) {
// 页码 + 数量
Page page = new Page(pageParam.getPageNo(), pageParam.getPageSize());
// 排序字段
String sortFields = pageParam.getFields();
if (StringUtils.isBlank(sortFields)) {
sortFields = "create_time";
}
List sortingFields = Arrays.asList(sortFields.split(","));
if (!CollectionUtil.isEmpty(sortingFields)) {
page.addOrder(sortingFields.stream().map(sortingField -> SortingField.ORDER_ASC.equals(pageParam.getOrder()) ?
OrderItem.asc(sortingField) : OrderItem.desc(sortingField))
.collect(Collectors.toList()));
}
return page;
}
/**
* 将拦截器添加到链中
* 由于 MybatisPlusInterceptor 不支持添加拦截器,所以只能全量设置
*
* @param interceptor 链
* @param inner 拦截器
* @param index 位置
*/
public static void addInterceptor(MybatisPlusInterceptor interceptor, InnerInterceptor inner, int index) {
List inners = new ArrayList(interceptor.getInterceptors());
inners.add(index, inner);
interceptor.setInterceptors(inners);
}
/**
* 获得 Table 对应的表名
*
* 兼容 MySQL 转义表名 `t_xxx`
*
* @param table 表
* @return 去除转移字符后的表名
*/
public static String getTableName(Table table) {
String tableName = table.getName();
if (tableName.startsWith(MYSQL_ESCAPE_CHARACTER) && tableName.endsWith(MYSQL_ESCAPE_CHARACTER)) {
tableName = tableName.substring(1, tableName.length() - 1);
}
return tableName;
}
/**
* 构建 Column 对象
*
* @param tableName 表名
* @param tableAlias 别名
* @param column 字段名
* @return Column 对象
*/
public static Column buildColumn(String tableName, Alias tableAlias, String column) {
if (tableAlias != null) {
tableName = tableAlias.getName();
}
return new Column(tableName + StringPool.DOT + column);
}
}
6.通用查询(待测试)
@Override
public List list(DrillData drillData) {
return list(new QueryWrapper().allEq(BeanUtil.beanToMap(drillData), false));
}
7.表字段格式为JSON的处理
package cn.shenzhihe.datarecord.model.entity;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* @class: DrillData
* @author: HeliosLy
* @since: 2023-09-18
* @description:
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName(value = "drill_data",autoResultMap = true)
@Schema(title = "DrillData对象")
public class DrillData extends BaseEntity implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@Schema(description = "环境辐射")
@TableField(value = "envm",typeHandler = JacksonTypeHandler.class)
private JSONObject envm;
@Schema(description = "风速")
@TableField(value ="wind_speed",typeHandler = FastjsonTypeHandler.class)
private JSONObject windSpeed;
@Schema(description = "风向")
@TableField(value ="wind_angle",typeHandler = FastjsonTypeHandler.class)
private JSONObject windAngle;
@Schema(description = "大气湿度")
@TableField(value ="humidity",typeHandler = FastjsonTypeHandler.class)
private JSONObject humidity;
@Schema(description = "大气温度")
@TableField(value ="temperature",typeHandler = FastjsonTypeHandler.class)
private JSONObject temperature;
@Schema(description = "气压")
@TableField(value ="pressure",typeHandler = FastjsonTypeHandler.class)
private JSONObject pressure;
@Schema(description = "降雨量")
@TableField(value ="rainfall",typeHandler = FastjsonTypeHandler.class)
private JSONObject rainfall;
@Schema(description = "总辐射")
@TableField(value ="total_radiation",typeHandler = FastjsonTypeHandler.class)
private JSONObject totalRadiation;
@Schema(description = "净辐射")
@TableField(value ="radiation",typeHandler = FastjsonTypeHandler.class)
private JSONObject radiation;
@Schema(description = "每小时蒸发量")
@TableField(value ="hour_evaporation",typeHandler = FastjsonTypeHandler.class)
private JSONObject hourEvaporation;
@Schema(description = "每天蒸发量")
@TableField(value ="day_evaporation",typeHandler = FastjsonTypeHandler.class)
private JSONObject dayEvaporation;
}
id, is_mock_envm, is_mock_weather, interval_time, data_sources, record_id, record_name, record_tag, record_start_time, record_end_time, record_description, duration, speed, playback_duration, playback_start_time, playback_end_time, envm, wind_speed, wind_angle, humidity, temperature, pressure, rainfall, total_radiation, radiation, hour_evaporation, day_evaporation, source_key, creator, updater, create_time, update_time
8.Mapper(表)忽略租户处理
package cn.shenzhihe.task.mapper;
import cn.shenzhihe.task.model.BaseMapperX;
import cn.shenzhihe.task.model.entity.SzhDict;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import org.apache.ibatis.annotations.Mapper;
/**
* @author: Maye
* @since: 2023-07-24
* @description:
*/
@Mapper
@InterceptorIgnore(tenantLine = "true")
public interface SzhDictMapper extends BaseMapperX {
}
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.fwqtg.net
创建 ASP.NET WebApi项目框架搭建 细节理解 ASP.NET WE服务器托管网B API 之属性路由 – 简书 授权 C# WebAPI 中过滤器Filter应用之IP访问控制_c#过滤器_MarcoPro的博客-CSDN博客 Log4Net配置 …