可以连表生成文件,但是不正确

This commit is contained in:
2025-10-21 23:51:55 +08:00
parent cd421afc6c
commit 6e76d30bac
28 changed files with 2131 additions and 604 deletions

View File

@@ -2,116 +2,83 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.5.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>top.yexuejc</groupId>
<artifactId>db2java-web</artifactId>
<version>1.0-SNAPSHOT</version>
<name>db2java-web</name>
<description>Web interface for db2java code generation tool</description>
<properties>
<compiler-plugin.version>3.14.0</compiler-plugin.version>
<maven.compiler.release>24</maven.compiler.release>
<java.version>17</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
<quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id>
<quarkus.platform.version>3.26.3</quarkus.platform.version>
<skipITs>true</skipITs>
<surefire-plugin.version>3.5.3</surefire-plugin.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>${quarkus.platform.group-id}</groupId>
<artifactId>${quarkus.platform.artifact-id}</artifactId>
<version>${quarkus.platform.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- Spring Boot Starter Web with Undertow -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc</artifactId>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<!-- Spring Boot Thymeleaf for UI -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- Spring Boot Configuration Processor -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Spring Boot Starter Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!-- db2java-core dependency -->
<dependency>
<groupId>top.yexuejc</groupId>
<artifactId>db2java-core</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>${quarkus.platform.group-id}</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<version>${quarkus.platform.version}</version>
<extensions>true</extensions>
<executions>
<execution>
<goals>
<goal>build</goal>
<goal>generate-code</goal>
<goal>generate-code-tests</goal>
<goal>native-image-agent</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>${compiler-plugin.version}</version>
<configuration>
<parameters>true</parameters>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire-plugin.version}</version>
<configuration>
<systemPropertyVariables>
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
<maven.home>${maven.home}</maven.home>
</systemPropertyVariables>
</configuration>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${surefire-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
<configuration>
<systemPropertyVariables>
<native.image.path>${project.build.directory}/${project.build.finalName}-runner
</native.image.path>
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
<maven.home>${maven.home}</maven.home>
</systemPropertyVariables>
</configuration>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>native</id>
<activation>
<property>
<name>native</name>
</property>
</activation>
<properties>
<skipITs>false</skipITs>
<quarkus.native.enabled>true</quarkus.native.enabled>
</properties>
</profile>
</profiles>
</project>
</project>

View File

@@ -0,0 +1,11 @@
package com.yexuejc.db2java.web;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

View File

@@ -0,0 +1,46 @@
package com.yexuejc.db2java.web.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "datasource")
public class DataSourceProperties {
private String url;
private String username;
private String password;
private String driverClassName;
// Getters and Setters
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getDriverClassName() {
return driverClassName;
}
public void setDriverClassName(String driverClassName) {
this.driverClassName = driverClassName;
}
}

View File

@@ -0,0 +1,272 @@
package com.yexuejc.db2java.web.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
@ConfigurationProperties(prefix = "generate")
public class GenerateProperties {
private String mode;
private String type;
private String out;
private String packageName;
private String author;
private boolean lombok;
private boolean merge;
private boolean override;
private String engine;
private List<String> ignoreTable;
private List<String> ignoreColumn;
private List<String> includeTable;
private Entity entity = new Entity();
private Controller controller = new Controller();
public static class Entity {
private boolean serialVersionUID;
private boolean serialAnnotation;
private boolean columnConstant;
private boolean chainModel;
private boolean toString;
private boolean fieldUseJavaDoc;
private boolean activeRecord;
private boolean serializable;
private boolean equalsAndHashCode;
private String fieldNaming;
private String tableAnnotation;
// Getters and Setters
public boolean isSerialVersionUID() {
return serialVersionUID;
}
public void setSerialVersionUID(boolean serialVersionUID) {
this.serialVersionUID = serialVersionUID;
}
public boolean isSerialAnnotation() {
return serialAnnotation;
}
public void setSerialAnnotation(boolean serialAnnotation) {
this.serialAnnotation = serialAnnotation;
}
public boolean isColumnConstant() {
return columnConstant;
}
public void setColumnConstant(boolean columnConstant) {
this.columnConstant = columnConstant;
}
public boolean isChainModel() {
return chainModel;
}
public void setChainModel(boolean chainModel) {
this.chainModel = chainModel;
}
public boolean isToString() {
return toString;
}
public void setToString(boolean toString) {
this.toString = toString;
}
public boolean isFieldUseJavaDoc() {
return fieldUseJavaDoc;
}
public void setFieldUseJavaDoc(boolean fieldUseJavaDoc) {
this.fieldUseJavaDoc = fieldUseJavaDoc;
}
public boolean isActiveRecord() {
return activeRecord;
}
public void setActiveRecord(boolean activeRecord) {
this.activeRecord = activeRecord;
}
public boolean isSerializable() {
return serializable;
}
public void setSerializable(boolean serializable) {
this.serializable = serializable;
}
public boolean isEqualsAndHashCode() {
return equalsAndHashCode;
}
public void setEqualsAndHashCode(boolean equalsAndHashCode) {
this.equalsAndHashCode = equalsAndHashCode;
}
public String getFieldNaming() {
return fieldNaming;
}
public void setFieldNaming(String fieldNaming) {
this.fieldNaming = fieldNaming;
}
public String getTableAnnotation() {
return tableAnnotation;
}
public void setTableAnnotation(String tableAnnotation) {
this.tableAnnotation = tableAnnotation;
}
}
public static class Controller {
private boolean mappingHyphen;
private boolean restStyle;
private String superClass;
// Getters and Setters
public boolean isMappingHyphen() {
return mappingHyphen;
}
public void setMappingHyphen(boolean mappingHyphen) {
this.mappingHyphen = mappingHyphen;
}
public boolean isRestStyle() {
return restStyle;
}
public void setRestStyle(boolean restStyle) {
this.restStyle = restStyle;
}
public String getSuperClass() {
return superClass;
}
public void setSuperClass(String superClass) {
this.superClass = superClass;
}
}
// Getters and Setters
public String getMode() {
return mode;
}
public void setMode(String mode) {
this.mode = mode;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getOut() {
return out;
}
public void setOut(String out) {
this.out = out;
}
public String getPackageName() {
return packageName;
}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public boolean isLombok() {
return lombok;
}
public void setLombok(boolean lombok) {
this.lombok = lombok;
}
public boolean isMerge() {
return merge;
}
public void setMerge(boolean merge) {
this.merge = merge;
}
public boolean isOverride() {
return override;
}
public void setOverride(boolean override) {
this.override = override;
}
public String getEngine() {
return engine;
}
public void setEngine(String engine) {
this.engine = engine;
}
public List<String> getIgnoreTable() {
return ignoreTable;
}
public void setIgnoreTable(List<String> ignoreTable) {
this.ignoreTable = ignoreTable;
}
public List<String> getIgnoreColumn() {
return ignoreColumn;
}
public void setIgnoreColumn(List<String> ignoreColumn) {
this.ignoreColumn = ignoreColumn;
}
public List<String> getIncludeTable() {
return includeTable;
}
public void setIncludeTable(List<String> includeTable) {
this.includeTable = includeTable;
}
public Entity getEntity() {
return entity;
}
public void setEntity(Entity entity) {
this.entity = entity;
}
public Controller getController() {
return controller;
}
public void setController(Controller controller) {
this.controller = controller;
}
}

View File

@@ -0,0 +1,168 @@
package com.yexuejc.db2java.web.controller;
import com.yexuejc.db2java.core.Db2JavaCore;
import com.yexuejc.db2java.core.generator.GenerationConfig;
import com.yexuejc.db2java.core.generator.GenerationResult;
import com.yexuejc.db2java.web.config.DataSourceProperties;
import com.yexuejc.db2java.web.config.GenerateProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Slf4j
@Controller
public class CodeGeneratorController {
@Autowired
private DataSourceProperties dataSourceProperties;
@Autowired
private GenerateProperties generateProperties;
@GetMapping("/")
public String index(Model model) {
model.addAttribute("dataSourceProperties", dataSourceProperties);
model.addAttribute("generateProperties", generateProperties);
String separator = System.lineSeparator();
model.addAttribute("separator", separator);
return "index";
}
@PostMapping("/generate")
public String generateCode(
@RequestParam String url,
@RequestParam String username,
@RequestParam String password,
@RequestParam String driverClassName,
@RequestParam String mode,
@RequestParam String type,
@RequestParam String out,
@RequestParam String packageName,
@RequestParam String author,
@RequestParam(defaultValue = "false") boolean lombok,
@RequestParam(defaultValue = "false") boolean merge,
@RequestParam(defaultValue = "false") boolean override,
@RequestParam String engine,
@RequestParam(required = false) String ignoreTable,
@RequestParam(required = false) String ignoreColumn,
@RequestParam(required = false) String includeTable,
RedirectAttributes redirectAttributes) {
System.out.println("接收到代码生成请求,参数如下:");
System.out.println("数据库URL: " + url);
System.out.println("数据库用户名: " + username);
System.out.println("数据库驱动类名: " + driverClassName);
System.out.println("生成模式: " + mode);
System.out.println("生成代码模式: " + type);
System.out.println("输出目录: " + out);
System.out.println("包名: " + packageName);
System.out.println("作者: " + author);
System.out.println("是否启用Lombok: " + lombok);
System.out.println("是否启用合并模式: " + merge);
System.out.println("是否覆盖文件: " + override);
System.out.println("模板引擎: " + engine);
System.out.println("忽略表列表: " + ignoreTable);
System.out.println("忽略字段列表: " + ignoreColumn);
System.out.println("包含表列表: " + includeTable);
System.out.println("===========================================");
try {
// 更新配置
dataSourceProperties.setUrl(url);
dataSourceProperties.setUsername(username);
dataSourceProperties.setPassword(password);
dataSourceProperties.setDriverClassName(driverClassName);
generateProperties.setMode(mode);
generateProperties.setType(type);
generateProperties.setOut(out);
generateProperties.setPackageName(packageName);
generateProperties.setAuthor(author);
generateProperties.setLombok(lombok);
generateProperties.setMerge(merge);
generateProperties.setOverride(override);
generateProperties.setEngine(engine);
generateProperties.setIgnoreTable(ignoreTable != null && !ignoreTable.isEmpty() ?
Arrays.asList(ignoreTable.split("[\\r\\n]+")) : null);
generateProperties.setIgnoreColumn(ignoreColumn != null && !ignoreColumn.isEmpty() ?
Arrays.asList(ignoreColumn.split("[\\r\\n]+")) : null);
generateProperties.setIncludeTable(includeTable != null && !includeTable.isEmpty() ?
Arrays.asList(includeTable.split("[\\r\\n]+")) : null);
// 创建生成配置
GenerationConfig config = new GenerationConfig();
config.setUrl(url);
config.setUsername(username);
config.setPassword(password);
config.setDriverClassName(driverClassName);
config.setMode(mode);
config.setType(type);
config.setOutDir(out);
config.setPackageName(packageName);
config.setAuthor(author);
config.setLombok(lombok);
config.setMerge(merge);
config.setOverride(override);
config.setEngine(engine);
// 处理忽略表列表
if (ignoreTable != null && !ignoreTable.isEmpty()) {
List<String> ignoreTableList = Arrays.stream(ignoreTable.split("[\\r\\n]+"))
.map(String::trim)
.filter(s -> !s.isEmpty())
.collect(Collectors.toList());
config.setIgnoreTables(ignoreTableList.toArray(new String[0]));
} else {
config.setIgnoreTables(new String[0]);
}
// 处理忽略字段列表
if (ignoreColumn != null && !ignoreColumn.isEmpty()) {
List<String> ignoreColumnList = Arrays.stream(ignoreColumn.split("[\\r\\n]+"))
.map(String::trim)
.filter(s -> !s.isEmpty())
.collect(Collectors.toList());
config.setIgnoreColumns(ignoreColumnList.toArray(new String[0]));
} else {
config.setIgnoreColumns(new String[0]);
}
// 处理包含表列表
if (includeTable != null && !includeTable.isEmpty()) {
List<String> includeTableList = Arrays.stream(includeTable.split("[\\r\\n]+"))
.map(String::trim)
.filter(s -> !s.isEmpty())
.collect(Collectors.toList());
config.setIncludeTables(includeTableList.toArray(new String[0]));
} else {
config.setIncludeTables(new String[0]);
}
// 设置额外配置,包括字段命名策略
Map<String, Object> extraConfig = new HashMap<>();
extraConfig.put("fieldNaming", generateProperties.getEntity().getFieldNaming());
config.setExtraConfig(extraConfig);
// 执行代码生成
GenerationResult result = Db2JavaCore.generate(config);
redirectAttributes.addFlashAttribute("success", "代码生成成功!共生成 " + result.getGeneratedFiles().size() + " 个文件。");
} catch (Exception e) {
System.err.println("代码生成失败: " + e.getMessage());
e.printStackTrace();
redirectAttributes.addFlashAttribute("error", "代码生成失败: " + e.getMessage());
}
return "redirect:/";
}
}

View File

@@ -0,0 +1,88 @@
server:
port: 8080
undertow:
# 设置IO线程数, 它主要执行非阻塞的任务, 它们会负责多个连接
io-threads: 4
# 阻塞任务线程池, 当执行类似servlet请求阻塞操作, undertow会从这个线程池中取得线程
worker-threads: 20
# 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理
buffer-size: 1024
# 是否分配的直接内存
direct-buffers: true
# 数据库配置
datasource:
url: jdbc:mysql://192.168.0.107:3306/globalVoice?characterEncoding=utf8&useUnicode=true&useSSL=false&allowPublicKeyRetrieval=true
username: intasect
password: 2$hGv1Dz[3)J7]BS]
driver-class-name: com.mysql.cj.jdbc.Driver
# 生成配置信息
generate:
# 生成模式hibernate,jpa,mybatis,mybatis-plus
mode: mybatis-plus
# 生成代码模式 file(直接在指定目录下生成代码),coding(在目录下生成/src/main/java和对应的package路径)
type: coding
# 输出目录
out: C:/0110_Workspace/yexuejc/db2java/export
# 包名
package: com.yexuejc.db2java.export
# 作者
author: yexuejc
# lombok模式 - 启用后不生成getter/setter方法使用@Data注解
lombok: false
# merge模式 - 是否合并已存在的文件
merge: true
# 覆盖已存在文件
override: true
# 模板引擎freemarker,velocity,beetl,enjoy
engine: freemarker
# 忽略表
ignore-table:
- sys_user
- sys_role
- sys_role_user
# 忽略字段
ignore-column:
- create_time
- update_time
# 包含表
include-table:
- sys_user
- sys_role
- sys_role_user
# 实体类配置
entity:
# 是否生成序列化版本ID
serialVersionUID: true
# 是否使用Serial注解(Java 14+)
serialAnnotation: false
# 是否生成字段常量
columnConstant: false
# 是否启用链式模型(返回this)
chainModel: false
# 是否生成toString方法(lombok=false时有效)
toString: true
# 是否使用JavaDoc注释字段
fieldUseJavaDoc: true
# 是否启用ActiveRecord模式
activeRecord: false
# 是否实现Serializable接口
serializable: true
# 是否生成equals和hashCode方法
equalsAndHashCode: false
# 字段命名策略: camelCase(驼峰), underline(下划线)
fieldNaming: camelCase
# 表名注解策略: none(无注解), table(使用@Table), entity(使用@Entity)
tableAnnotation: none
controller:
# 驼峰转连字符(默认 false
## <code>@RequestMapping("/managerUserActionHistory")</code> -> <code>@RequestMapping("/manager-user-action-history")</code>
mappingHyphen: true
# 生成 <code>@RestController</code> 控制器(默认 false
## <code>@Controller</code> -> <code>@RestController</code>
restStyle: true
# 自定义继承的Controller类全称带包名,默认为空
## superClass: com.yexuejc.db2java.export.controller.BaseController
superClass:

View File

@@ -0,0 +1,179 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>DB2Java代码生成器</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container mt-5">
<h1 class="mb-4">DB2Java代码生成器</h1>
<!-- 显示成功或错误消息 -->
<div th:if="${success}" class="alert alert-success alert-dismissible fade show" role="alert">
<span th:text="${success}"></span>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<div th:if="${error}" class="alert alert-danger alert-dismissible fade show" role="alert">
<span th:text="${error}"></span>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<form action="/generate" method="post">
<div class="card mb-4">
<div class="card-header">
<h5>数据库配置</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-6 mb-3">
<label for="url" class="form-label">数据库URL</label>
<input type="text" class="form-control" id="url" name="url"
th:value="${dataSourceProperties.url}" required>
</div>
<div class="col-md-6 mb-3">
<label for="driverClassName" class="form-label">驱动类名</label>
<input type="text" class="form-control" id="driverClassName" name="driverClassName"
th:value="${dataSourceProperties.driverClassName}" required>
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="username" class="form-label">用户名</label>
<input type="text" class="form-control" id="username" name="username"
th:value="${dataSourceProperties.username}" required>
</div>
<div class="col-md-6 mb-3">
<label for="password" class="form-label">密码</label>
<input type="password" class="form-control" id="password" name="password"
th:value="${dataSourceProperties.password}" required>
</div>
</div>
</div>
</div>
<div class="card mb-4">
<div class="card-header">
<h5>生成配置</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-6 mb-3">
<label for="mode" class="form-label">生成模式</label>
<select class="form-select" id="mode" name="mode" required>
<option value="hibernate" th:selected="${generateProperties.mode == 'hibernate'}">
Hibernate
</option>
<option value="jpa" th:selected="${generateProperties.mode == 'jpa'}">JPA</option>
<option value="mybatis" th:selected="${generateProperties.mode == 'mybatis'}">MyBatis
</option>
<option value="mybatis-plus" th:selected="${generateProperties.mode == 'mybatis-plus'}">
MyBatis-Plus
</option>
</select>
</div>
<div class="col-md-6 mb-3">
<label for="type" class="form-label">生成代码模式</label>
<select class="form-select" id="type" name="type" required>
<option value="file" th:selected="${generateProperties.type == 'file'}">File</option>
<option value="coding" th:selected="${generateProperties.type == 'coding'}">Coding</option>
</select>
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="out" class="form-label">输出目录</label>
<input type="text" class="form-control" id="out" name="out"
th:value="${generateProperties.out}" required>
</div>
<div class="col-md-6 mb-3">
<label for="packageName" class="form-label">包名</label>
<input type="text" class="form-control" id="packageName" name="packageName"
th:value="${generateProperties.packageName}" required>
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="author" class="form-label">作者</label>
<input type="text" class="form-control" id="author" name="author"
th:value="${generateProperties.author}">
</div>
<div class="col-md-6 mb-3">
<label for="engine" class="form-label">模板引擎</label>
<select class="form-select" id="engine" name="engine" required>
<option value="freemarker" th:selected="${generateProperties.engine == 'freemarker'}">
FreeMarker
</option>
<option value="velocity" th:selected="${generateProperties.engine == 'velocity'}">Velocity
</option>
<option value="beetl" th:selected="${generateProperties.engine == 'beetl'}">Beetl</option>
<option value="enjoy" th:selected="${generateProperties.engine == 'enjoy'}">Enjoy</option>
</select>
</div>
</div>
<div class="row">
<div class="col-md-3 mb-3">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="lombok" name="lombok"
th:checked="${generateProperties.lombok}">
<label class="form-check-label" for="lombok">启用Lombok</label>
</div>
</div>
<div class="col-md-3 mb-3">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="merge" name="merge"
th:checked="${generateProperties.merge}">
<label class="form-check-label" for="merge">合并模式</label>
</div>
</div>
<div class="col-md-3 mb-3">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="override" name="override"
th:checked="${generateProperties.override}">
<label class="form-check-label" for="override">覆盖文件</label>
</div>
</div>
</div>
</div>
</div>
<div class="card mb-4">
<div class="card-header">
<h5>表和字段配置</h5>
</div>
<div class="card-body">
<div class="mb-3">
<label for="includeTable" class="form-label">包含表(每行一个)</label>
<textarea class="form-control" id="includeTable" name="includeTable" rows="3"
th:text="${generateProperties?.includeTable != null ? #strings.listJoin(generateProperties.includeTable, separator) : ''}">
</textarea>
</div>
<div class="mb-3">
<label for="ignoreTable" class="form-label">忽略表(每行一个)</label>
<textarea class="form-control" id="ignoreTable" name="ignoreTable" rows="3"
th:text="${generateProperties?.ignoreTable != null ? #strings.listJoin(generateProperties.ignoreTable, separator) : ''}"></textarea>
</div>
<div class="mb-3">
<label for="ignoreColumn" class="form-label">忽略字段(每行一个)</label>
<textarea class="form-control" id="ignoreColumn" name="ignoreColumn" rows="3"
th:text="${generateProperties?.ignoreColumn != null ? #strings.listJoin(generateProperties.ignoreColumn, separator) : ''}"></textarea>
</div>
</div>
</div>
<div class="d-grid gap-2 d-md-flex justify-content-md-end">
<button type="submit" class="btn btn-primary btn-lg">生成代码</button>
</div>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>