Browse Source

entity。mapper相关,自动生成

master
review512jwy@163.com 1 month ago
parent
commit
115cdae966
  1. 26
      pom.xml
  2. 242
      src/main/java/com/youlai/boot/codegen/MyBatisPlusGenerator.java
  3. 90
      src/main/resources/templates/codegen/ftl/entity.java.ftl

26
pom.xml

@ -64,6 +64,12 @@
<weixin-java-miniapp.version>4.8.1.B</weixin-java-miniapp.version> <weixin-java-miniapp.version>4.8.1.B</weixin-java-miniapp.version>
<freemarker.version>2.3.34</freemarker.version>
<jts-core.version>1.20.0</jts-core.version>
<geohash.version>1.4.0</geohash.version>
</properties> </properties>
@ -276,6 +282,26 @@
<version>${weixin-java-miniapp.version}</version> <version>${weixin-java-miniapp.version}</version>
</dependency> </dependency>
<!-- Source: https://mvnrepository.com/artifact/org.freemarker/freemarker -->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>${freemarker.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.locationtech.jts/jts-core -->
<dependency>
<groupId>org.locationtech.jts</groupId>
<artifactId>jts-core</artifactId>
<version>${jts-core.version}</version>
</dependency>
<dependency>
<groupId>ch.hsr</groupId>
<artifactId>geohash</artifactId>
<version>${geohash.version}</version>
</dependency>
<!-- 动态多数据源 --> <!-- 动态多数据源 -->
<!--<dependency> <!--<dependency>
<groupId>com.baomidou</groupId> <groupId>com.baomidou</groupId>

242
src/main/java/com/youlai/boot/codegen/MyBatisPlusGenerator.java

@ -0,0 +1,242 @@
package com.youlai.boot.codegen;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.po.TableField;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.IColumnType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.type.ITypeConvertHandler;
import com.baomidou.mybatisplus.generator.type.TypeRegistry;
import org.springframework.util.CollectionUtils;
import java.util.*;
public class MyBatisPlusGenerator {
/**
* 表配置核心
*/
static class TableConfig {
private final String tableName;
private final IdType idType;
private final String module;
public TableConfig(String tableName, IdType idType, String module) {
this.tableName = tableName;
this.idType = idType;
this.module = module;
}
public String getTableName() {
return tableName;
}
public IdType getIdType() {
return idType;
}
public String getModule() {
return module;
}
}
/**
* 自定义类型转换
*/
public static class MyCustomTypeConvertHandler implements ITypeConvertHandler {
@Override
public IColumnType convert(com.baomidou.mybatisplus.generator.config.GlobalConfig globalConfig,
TypeRegistry typeRegistry,
TableField.MetaInfo metaInfo) {
String columnType = metaInfo.getTypeName();
String columnName = metaInfo.getColumnName();
System.out.println(">>> [字段处理] column: " + columnName +
", columnType: " + columnType);
if (columnType != null &&
(columnType.toLowerCase().contains("geometry")
|| columnType.toLowerCase().contains("point"))) {
System.out.println(">>> 命中地理类型字段,使用 Point");
return new IColumnType() {
@Override
public String getType() {
return "Point";
}
@Override
public String getPkg() {
return "org.locationtech.jts.geom";
}
};
}
return typeRegistry.getColumnType(metaInfo);
}
}
public static void main(String[] args) {
String url = "jdbc:mysql://rm-bp11k2zm2fr7864428o.mysql.rds.aliyuncs.com:3306/stray_animals_back?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai";
String username = "zhc";
String password = "Youqu48bnb1";
/**
* 表维度配置你只需要改这里🔥
*/
List<TableConfig> tableConfigs = Arrays.asList(
new TableConfig("mini_stray_animal", IdType.AUTO, "mini")
// ,new TableConfig("mini_stray_animal", IdType.AUTO, "mini")
// ,new TableConfig("mini_stray_animal", IdType.INPUT, "minitest")
//
// ,new TableConfig("mini_stray_animal", IdType.NONE, "minitest2")
);
// 按 module + idType 分组(企业级写法)
Map<String, Map<IdType, List<String>>> grouped = new HashMap<>();
for (TableConfig config : tableConfigs) {
grouped
.computeIfAbsent(config.getModule(), k -> new HashMap<>())
.computeIfAbsent(config.getIdType(), k -> new ArrayList<>())
.add(config.getTableName());
}
// 分批生成
for (Map.Entry<String, Map<IdType, List<String>>> moduleEntry : grouped.entrySet()) {
String module = moduleEntry.getKey();
for (Map.Entry<IdType, List<String>> idEntry : moduleEntry.getValue().entrySet()) {
generate(url, username, password,
idEntry.getValue(),
idEntry.getKey(),
module);
}
}
}
/**
* 核心生成方法
*/
private static void generate(String url,
String username,
String password,
List<String> tables,
IdType idType,
String moduleName) {
if (CollectionUtils.isEmpty(tables)) {
System.out.println(">>> [跳过] tables为空");
return;
}
System.out.println(">>> 开始生成:module=" + moduleName + " tables=" + tables);
FastAutoGenerator.create(url, username, password)
// 全局配置
.globalConfig(builder -> builder
.author("jwy")
.disableOpenDir()
.dateType(DateType.TIME_PACK)
.commentDate("")
)
// 数据源
.dataSourceConfig(builder -> builder
.schema("stray_animals_back")
.typeConvertHandler(new MyCustomTypeConvertHandler())
)
// 包 + 路径(动态模块)
.packageConfig(builder -> builder
.parent("com.youlai.boot")
.moduleName(moduleName)
.entity("model.entity")
.mapper("mapper")
.xml("mapper")
.pathInfo(getPathInfo(moduleName))
)
// 策略
.strategyConfig(builder -> {
builder.addInclude(tables);
// entity
builder.entityBuilder()
.enableFileOverride()
.enableLombok()
.enableTableFieldAnnotation()
.naming(NamingStrategy.underline_to_camel)
.columnNaming(NamingStrategy.underline_to_camel)
.enableChainModel()
.enableRemoveIsPrefix()
.logicDeleteColumnName("deleted")
.idType(idType);
// mapper
builder.mapperBuilder()
.enableFileOverride()
.enableBaseResultMap()
.enableBaseColumnList()
.formatMapperFileName("%sMapper")
.formatXmlFileName("%sMapper");
// 不生成 service / controller(彻底关闭)
builder.serviceBuilder().disable();
builder.controllerBuilder().disable();
})
// 模板(只保留 entity)
.templateConfig(builder -> builder
.entity("templates/codegen/ftl/entity.java")
.disable(
com.baomidou.mybatisplus.generator.config.TemplateType.SERVICE,
com.baomidou.mybatisplus.generator.config.TemplateType.SERVICE_IMPL,
com.baomidou.mybatisplus.generator.config.TemplateType.CONTROLLER
)
)
.execute();
}
/**
* 动态路径按模块
*/
private static Map<OutputFile, String> getPathInfo(String moduleName) {
String projectRoot = System.getProperty("user.dir");
Map<OutputFile, String> pathInfo = new HashMap<>();
String base = projectRoot + "/src/main/java/com/youlai/boot/" + moduleName;
pathInfo.put(OutputFile.entity, base + "/model/entity");
pathInfo.put(OutputFile.mapper, base + "/mapper");
pathInfo.put(OutputFile.xml,
projectRoot + "/src/main/resources/mapper/" + moduleName + "/");
// pathInfo.put(OutputFile.service,
// projectRoot + "/src/main/java/com/youlai/boot/mini/service");
//
// pathInfo.put(OutputFile.serviceImpl,
// projectRoot + "/src/main/java/com/youlai/boot/mini/service/impl");
//
// pathInfo.put(OutputFile.controller,
// projectRoot + "/src/main/java/com/youlai/boot/mini/controller");
return pathInfo;
}
}

90
src/main/resources/templates/codegen/ftl/entity.java.ftl

@ -0,0 +1,90 @@
package ${package.Entity};
import com.baomidou.mybatisplus.annotation.*;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;
import java.io.Serializable;
<#-- 日期导入 -->
<#list table.fields as field>
<#if field.propertyType == "LocalDate" || field.propertyType == "LocalDateTime">
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
<#break>
</#if>
</#list>
<#-- 导入 org.locationtech.jts.geom.Point 类型 -->
<#list table.fields as field>
<#if field.propertyType == "Point">
import org.locationtech.jts.geom.Point;
import com.pet.map.back.handler.PointTypeHandler;
<#break>
</#if>
</#list>
<#-- BigDecimal 导入 -->
<#list table.fields as field>
<#if field.propertyType == "BigDecimal">
import java.math.BigDecimal;
<#break>
</#if>
</#list>
@Getter
@Setter
@ToString
@Accessors(chain = true)
@TableName("${table.name}")
@Schema(description = "${table.comment!}")
public class ${entity} implements Serializable {
<#-- 主键字段 -->
<#assign hasPk = false>
<#list table.fields as field>
<#if field.keyFlag>
<#assign hasPk = true>
@TableId(value = "${field.name}", type = IdType.${idType!"ASSIGN_ID"})
@Schema(description = "${field.comment!}")
<#if field.propertyType == "LocalDate">
JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date ${field.propertyName};
<#elseif field.propertyType == "LocalDateTime">
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date ${field.propertyName};
<#else>
private ${field.propertyType} ${field.propertyName};
</#if>
</#if>
</#list>
<#-- 普通字段 -->
<#list table.fields as field>
<#if !field.keyFlag>
<#if field.propertyType == "Point">
@TableField(value = "${field.name}", typeHandler = PointTypeHandler.class)
<#else>
@TableField("${field.name}")
</#if>
@Schema(description = "${field.comment!}")
<#if field.propertyType == "LocalDate">
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date ${field.propertyName};
<#elseif field.propertyType == "LocalDateTime">
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date ${field.propertyName};
<#else>
private ${field.propertyType} ${field.propertyName};
</#if>
</#if>
</#list>
<#-- 无主键表的额外处理 -->
<#if !hasPk>
<#-- 在这里可以添加无主键表特有的方法或注释 -->
<#-- 例如,可能需要提供手动主键生成策略或者修改操作方法 -->
</#if>
}
Loading…
Cancel
Save