源码
表结构

代码的目录结构
后端代码

前端代码

查询数据库的表
前端
后端
- 只查询
当前数据库
的表去除掉
定时任务和生成器
的表格去除掉
已经导入的表格

xml
<select id="selectDbTableList" parameterType="GenTable" resultMap="GenTableResult">
select table_name, table_comment, create_time, update_time
from information_schema.tables
where table_schema = (select database()) <!-- 查询当前数据库中的表 -->
AND table_name NOT LIKE 'qrtz_%' <!-- 排除表名以 'qrtz_' 开头的表 -->
AND table_name NOT LIKE 'gen_%' <!-- 排除表名以 'gen_' 开头的表 -->
AND table_name NOT IN (select table_name from gen_table) <!-- 排除已经在 gen_table 表中的表 -->
<if test="tableName != null and tableName != ''">
AND lower(table_name) like lower(concat('%', #{tableName}, '%')) <!-- 如果 tableName 不为空,按表名模糊查询 -->
</if>
<if test="tableComment != null and tableComment != ''">
AND lower(table_comment) like lower(concat('%', #{tableComment}, '%')) <!-- 如果 tableComment 不为空,按表注释模糊查询 -->
</if>
<if test="params.beginTime != null and params.beginTime != ''"><!-- 如果 beginTime 不为空,按创建时间起始时间查询 -->
AND date_format(create_time,'%y%m%d') >= date_format(#{params.beginTime},'%y%m%d')
</if>
<if test="params.endTime != null and params.endTime != ''"><!-- 如果 endTime 不为空,按创建时间结束时间查询 -->
AND date_format(create_time,'%y%m%d') <= date_format(#{params.endTime},'%y%m%d')
</if>
order by create_time desc <!-- 按创建时间降序排列 -->
</select>
导入表结构
流程

前端
对选中的表进行处理

导入表的后端接口
后端
controller

mapper层

导入表结构的 数据库代码
- 循环遍历 前端传入的数据
- 存储表的信息
- 存储列的信息
java
for (GenTable table : tableList)
{
String tableName = table.getTableName();
// 初始化表信息
GenUtils.initTable(table, operName);
// 插入表信息
int row = genTableMapper.insertGenTable(table);
if (row > 0)
{
// 保存列信息
List<GenTableColumn> genTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName);
for (GenTableColumn column : genTableColumns)
{
GenUtils.initColumnField(column, table);
genTableColumnMapper.insertGenTableColumn(column);
}
}
}
获取
列信息
的mapper
xml
<select id="selectDbTableColumnsByName" parameterType="String" resultMap="GenTableColumnResult">
<!-- 选择列的详细信息 -->
select column_name,
<!-- 判断列是否为必需(不可为空且不是主键) -->
(case when (is_nullable = 'no' <![CDATA[ && ]]> column_key != 'PRI') then '1' else '0' end) as is_required,
<!-- 判断列是否为主键 -->
(case when column_key = 'PRI' then '1' else '0' end) as is_pk,
<!-- 获取列的序号位置 -->
ordinal_position as sort,
<!-- 获取列的注释 -->
column_comment,
<!-- 判断列是否为自动递增 -->
(case when extra = 'auto_increment' then '1' else '0' end) as is_increment,
<!-- 获取列的数据类型 -->
column_type
from information_schema.columns
<!-- 过滤当前数据库模式中指定表的列 -->
where table_schema = (select database())
and table_name = (#{tableName})
<!-- 按列的序号位置排序 -->
order by ordinal_position
</select>
初始化 列的信息
- 根据数据库的
列名
使用驼峰命名法
进行设置- 根据 原本的 列类型 设置对应的 java的类型
- 根据 列的名称 判断 大致的 前段的 筛选 条件的方式,是EQ,LIKE,RADIO
java
public static void initColumnField(GenTableColumn column, GenTable table)
{
// 获取列的数据类型
String dataType = getDbType(column.getColumnType());
// 获取列的名称
String columnName = column.getColumnName();
// 设置表ID
column.setTableId(table.getTableId());
// 设置创建者
column.setCreateBy(table.getCreateBy());
// 设置Java字段名
column.setJavaField(StringUtils.toCamelCase(columnName));
// 设置默认Java类型为String,默认查询方式为EQ
column.setJavaType(GenConstants.TYPE_STRING);
column.setQueryType(GenConstants.QUERY_EQ);
// 根据数据类型设置HTML类型
if (arraysContains(GenConstants.COLUMNTYPE_STR, dataType) || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType))
{
// 如果字符串长度超过500,设置为文本域,否则设置为输入框
Integer columnLength = getColumnLength(column.getColumnType());
String htmlType = columnLength >= 500 || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType) ? GenConstants.HTML_TEXTAREA : GenConstants.HTML_INPUT;
column.setHtmlType(htmlType);
}
else if (arraysContains(GenConstants.COLUMNTYPE_TIME, dataType))
{
// 时间类型设置Java类型为Date,HTML类型为DATETIME
column.setJavaType(GenConstants.TYPE_DATE);
column.setHtmlType(GenConstants.HTML_DATETIME);
}
else if (arraysContains(GenConstants.COLUMNTYPE_NUMBER, dataType))
{
// 数字类型设置HTML类型为输入框
column.setHtmlType(GenConstants.HTML_INPUT);
// 如果是浮点型,设置Java类型为BigDecimal
String[] str = StringUtils.split(StringUtils.substringBetween(column.getColumnType(), "(", ")"), ",");
if (str != null && str.length == 2 && Integer.parseInt(str[1]) > 0)
{
column.setJavaType(GenConstants.TYPE_BIGDECIMAL);
}
// 如果是整型,且长度小于等于10,设置Java类型为Integer
else if (str != null && str.length == 1 && Integer.parseInt(str[0]) <= 10)
{
column.setJavaType(GenConstants.TYPE_INTEGER);
}
// 否则设置为Long类型
else
{
column.setJavaType(GenConstants.TYPE_LONG);
}
}
// 默认所有字段都需要插入
column.setIsInsert(GenConstants.REQUIRE);
// 如果列名不在不可编辑列表中且不是主键,设置为可编辑
if (!arraysContains(GenConstants.COLUMNNAME_NOT_EDIT, columnName) && !column.isPk())
{
column.setIsEdit(GenConstants.REQUIRE);
}
// 如果列名不在不可列表中且不是主键,设置为列表字段
if (!arraysContains(GenConstants.COLUMNNAME_NOT_LIST, columnName) && !column.isPk())
{
column.setIsList(GenConstants.REQUIRE);
}
// 如果列名不在不可查询列表中且不是主键,设置为查询字段
if (!arraysContains(GenConstants.COLUMNNAME_NOT_QUERY, columnName) && !column.isPk())
{
column.setIsQuery(GenConstants.REQUIRE);
}
// 如果列名以name结尾,设置查询类型为LIKE
if (StringUtils.endsWithIgnoreCase(columnName, "name"))
{
column.setQueryType(GenConstants.QUERY_LIKE);
}
// 如果列名以status结尾,设置HTML类型为单选框
if (StringUtils.endsWithIgnoreCase(columnName, "status"))
{
column.setHtmlType(GenConstants.HTML_RADIO);
}
// 如果列名以type或sex结尾,设置HTML类型为下拉框
else if (StringUtils.endsWithIgnoreCase(columnName, "type") || StringUtils.endsWithIgnoreCase(columnName, "sex"))
{
column.setHtmlType(GenConstants.HTML_SELECT);
}
// 如果列名以image结尾,设置HTML类型为图片上传控件
else if (StringUtils.endsWithIgnoreCase(columnName, "image"))
{
column.setHtmlType(GenConstants.HTML_IMAGE_UPLOAD);
}
// 如果列名以file结尾,设置HTML类型为文件上传控件
else if (StringUtils.endsWithIgnoreCase(columnName, "file"))
{
column.setHtmlType(GenConstants.HTML_FILE_UPLOAD);
}
// 如果列名以content结尾,设置HTML类型为富文本控件
else if (StringUtils.endsWithIgnoreCase(columnName, "content"))
{
column.setHtmlType(GenConstants.HTML_EDITOR);
}
}
批量生成代码

controller层

Service层
- 创建一个
zip流
- 遍历表名,依次生成对应的代码
java
@Override
public byte[] downloadCode(String[] tableNames)
{
// 创建一个字节数组输出流
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
// 创建一个Zip输出流
ZipOutputStream zip = new ZipOutputStream(outputStream);
// 遍历所有表名,生成代码并添加到Zip输出流中
for (String tableName : tableNames)
{
generatorCode(tableName, zip);
}
// 关闭Zip输出流
IOUtils.closeQuietly(zip);
// 返回生成的字节数组
return outputStream.toByteArray();
}

获取
上下文
和模板文件

将上下文的内容加到写到模板文件中

使用response输出流输出zip文件
java
private void genCode(HttpServletResponse response, byte[] data) throws IOException
{
// 重置响应以清除任何先前的数据
response.reset();
// 允许跨域请求
response.addHeader("Access-Control-Allow-Origin", "*");
// 向客户端公开 Content-Disposition 头
response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
// 设置 Content-Disposition 头以指示文件附件名称为 "ruoyi.zip"
response.setHeader("Content-Disposition", "attachment; filename=\"ruoyi.zip\"");
// 添加 Content-Length 头以指定数据的长度
response.addHeader("Content-Length", "" + data.length);
// 设置内容类型以指示二进制文件
response.setContentType("application/octet-stream; charset=UTF-8");
// 将数据写入响应输出流
IOUtils.write(data, response.getOutputStream());
}