ruoyi-vue-plus-代码生成功能
框架代码生成功能可快速构建项目的基础文件 , 如 : Controller , Service , Mapper 等基础架构文件 . 该框架是在页面进行配置生成信息 , 以实现快速开发 , 能够提高前期开发效率
ruoyi-vue-plus应用文档 : https://plus-doc.dromara.org (opens new window)
# 快速应用
应用大致步骤
- 导入表
- 设置配置表生成信息
- 下载生成代码
- 导入sql
- copy 前后端
- 启用...
注意
- 每个表必须包含有 : create_by , create_time , update_by , update_time 字段
- 树表 必须包含有 指向指定字段(一般用id) , 用于指向父级数据
# 基本信息
无关键信息填写
# 字段信息
填写信息说明
物理类型 => SQL应用的类型
Java类型 => 对象属性类型
Java属性 => 对象属性名称
选定字段是否采用 插入/编辑/列表/查询 => 新增是否显示/编辑是否显示/列表是否显示/查询字段显示
查询方式 : 选中查询后 , 指定SQL查询方式
显示类型 : 在 编辑/新增 时 , 更加的方便使用
必填 : 勾选后 , 插入的时候必须填写
# 生成信息
单表
关注 包路径/模块名
树表
关注 包路径/模块名/树id字段/树父id字段/树名
大量数据不适合使用 , 数据分级主要通过前端分级展示
# 配置文件
generator.yml
配置文件*
# 代码生成
gen:
# 作者
author: bozhu
# 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool
packageName: com.ruoyi.system
# 自动去除表前缀,默认是false
autoRemovePre: false
# 表前缀(生成类名不会包含表前缀,多个用逗号分隔)
tablePrefix: sys_
根据实际情况修改配置
# 核心业务
# 导入列表
根据 information_schem
数据库表信息查询
获取库表基础信息 GenController#dataLis()
@SaCheckPermission("tool:gen:list")
@GetMapping("/db/list")
public TableDataInfo<GenTable> dataList(GenTable genTable, PageQuery pageQuery) {
return genTableService.selectPageDbTableList(genTable, pageQuery);
}
业务层 (略过 , 无必要逻辑代码)
SQL执行语句 GenTableMapper.selectPageDbTableList() (该方法适配不同数据源应用 , 只需关注MySQL应用方式即可)
点击展开
<select id="selectPageDbTableList" resultMap="GenTableResult">
<if test="@com.ruoyi.common.helper.DataBaseHelper@isMySql()">
select table_name, table_comment, create_time, update_time
from information_schema.tables
where table_schema = (select database())
AND table_name NOT LIKE 'xxl_job_%' AND table_name NOT LIKE 'gen_%'
AND table_name NOT IN (select table_name from gen_table)
<if test="genTable.tableName != null and genTable.tableName != ''">
AND lower(table_name) like lower(concat('%', #{genTable.tableName}, '%'))
</if>
<if test="genTable.tableComment != null and genTable.tableComment != ''">
AND lower(table_comment) like lower(concat('%', #{genTable.tableComment}, '%'))
</if>
order by create_time desc
</if>
<if test="@com.ruoyi.common.helper.DataBaseHelper@isOracle()">
select lower(dt.table_name) as table_name, dtc.comments as table_comment, uo.created as create_time, uo.last_ddl_time as update_time
from user_tables dt, user_tab_comments dtc, user_objects uo
where dt.table_name = dtc.table_name
and dt.table_name = uo.object_name
and uo.object_type = 'TABLE'
AND dt.table_name NOT LIKE 'XXL_JOB_%' AND dt.table_name NOT LIKE 'GEN_%'
AND lower(dt.table_name) NOT IN (select table_name from gen_table)
<if test="genTable.tableName != null and genTable.tableName != ''">
AND lower(dt.table_name) like lower(concat(concat('%', #{genTable.tableName}), '%'))
</if>
<if test="genTable.tableComment != null and genTable.tableComment != ''">
AND lower(dtc.comments) like lower(concat(concat('%', #{genTable.tableComment}), '%'))
</if>
order by create_time desc
</if>
<if test="@com.ruoyi.common.helper.DataBaseHelper@isPostgerSql()">
select table_name, table_comment, create_time, update_time
from (
SELECT c.relname AS table_name,
obj_description(c.oid) AS table_comment,
CURRENT_TIMESTAMP AS create_time,
CURRENT_TIMESTAMP AS update_time
FROM pg_class c
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE (c.relkind = ANY (ARRAY ['r'::"char", 'p'::"char"]))
AND c.relname != 'spatial_%'::text
AND n.nspname = 'public'::name
AND n.nspname <![CDATA[ <> ]]> ''::name
) list_table
where table_name NOT LIKE 'xxl_job_%' AND table_name NOT LIKE 'gen_%'
AND table_name NOT IN (select table_name from gen_table)
<if test="genTable.tableName != null and genTable.tableName != ''">
AND lower(table_name) like lower(concat('%', #{genTable.tableName}, '%'))
</if>
<if test="genTable.tableComment != null and genTable.tableComment != ''">
AND lower(table_comment) like lower(concat('%', #{genTable.tableComment}, '%'))
</if>
order by create_time desc
</if>
<if test="@com.ruoyi.common.helper.DataBaseHelper@isSqlServer()">
SELECT cast(D.NAME as nvarchar) as table_name,
cast(F.VALUE as nvarchar) as table_comment,
crdate as create_time,
refdate as update_time
FROM SYSOBJECTS D
INNER JOIN SYS.EXTENDED_PROPERTIES F ON D.ID = F.MAJOR_ID
AND F.MINOR_ID = 0 AND D.XTYPE = 'U' AND D.NAME != 'DTPROPERTIES'
AND D.NAME NOT LIKE 'xxl_job_%' AND D.NAME NOT LIKE 'gen_%'
AND D.NAME NOT IN (select table_name from gen_table)
<if test="genTable.tableName != null and genTable.tableName != ''">
AND lower(D.NAME) like lower(concat(N'%', N'${genTable.tableName}', N'%'))
</if>
<if test="genTable.tableComment != null and genTable.tableComment != ''">
AND lower(CAST(F.VALUE AS nvarchar)) like lower(concat(N'%', N'${genTable.tableComment}', N'%'))
</if>
order by crdate desc
</if>
</select>
实际执行的SQL
以下SQL是查询当前数据源的所有库表信息 , 因此需要加多层约束过滤
SELECT
table_name,
table_comment,
create_time,
update_time
FROM
information_schema.TABLES
WHERE
# 仅保留当前库的表
table_schema = (SELECT DATABASE())
# 排除不必要的表名(模糊匹配)
AND table_name NOT LIKE 'xxl_job_%'
AND table_name NOT LIKE 'gen_%'
# 排除已经导入的表
AND table_name NOT IN ( SELECT table_name FROM gen_table )
ORDER BY
create_time DESC
LIMIT 10
DataBaseHelper
数据源判断
点击展开
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class DataBaseHelper {
private static final DynamicRoutingDataSource DS = SpringUtils.getBean(DynamicRoutingDataSource.class);
/**
* 获取当前数据库类型
*/
public static DataBaseType getDataBaseType() {
DataSource dataSource = DS.determineDataSource();
try (Connection conn = dataSource.getConnection()) {
DatabaseMetaData metaData = conn.getMetaData();
String databaseProductName = metaData.getDatabaseProductName();
return DataBaseType.find(databaseProductName);
} catch (SQLException e) {
throw new ServiceException(e.getMessage());
}
}
public static boolean isMySql() {
return DataBaseType.MY_SQL == getDataBaseType();
}
public static boolean isOracle() {
return DataBaseType.ORACLE == getDataBaseType();
}
public static boolean isPostgerSql() {
return DataBaseType.POSTGRE_SQL == getDataBaseType();
}
public static boolean isSqlServer() {
return DataBaseType.SQL_SERVER == getDataBaseType();
}
public static String findInSet(Object var1, String var2) {
DataBaseType dataBasyType = getDataBaseType();
String var = Convert.toStr(var1);
if (dataBasyType == DataBaseType.SQL_SERVER) {
// charindex(',100,' , ',0,100,101,') <> 0
return "charindex('," + var + ",' , ','+" + var2 + "+',') <> 0";
} else if (dataBasyType == DataBaseType.POSTGRE_SQL) {
// (select position(',100,' in ',0,100,101,')) <> 0
return "(select position('," + var + ",' in ','||" + var2 + "||',')) <> 0";
} else if (dataBasyType == DataBaseType.ORACLE) {
// instr(',0,100,101,' , ',100,') <> 0
return "instr(','||" + var2 + "||',' , '," + var + ",') <> 0";
}
// find_in_set('100' , '0,100,101')
return "find_in_set('" + var + "' , " + var2 + ") <> 0";
}
}
# 导入生成表
当用户选中需要导入表时 , 接口会 根据 表名称 进行插入 gen_table
表 和 gen_table_column
表
导入表结构 GenController#importTableSave()
@SaCheckPermission("tool:gen:import")
@Log(title = "代码生成", businessType = BusinessType.IMPORT)
@PostMapping("/importTable")
public R<Void> importTableSave(String tables) {
String[] tableNames = Convert.toStrArray(tables);
// 查询表信息
List<GenTable> tableList = genTableService.selectDbTableListByNames(tableNames);
// 导入库表 gen_table , gen_table_column
genTableService.importGenTable(tableList);
return R.ok();
}
导入核心业务 GenTableServiceImpl#importGenTable()
@Transactional(rollbackFor = Exception.class)
@Override
public void importGenTable(List<GenTable> tableList) {
String operName = LoginHelper.getUsername();
try {
for (GenTable table : tableList) {
String tableName = table.getTableName();
// 初始化 表基础信息 并保存
GenUtils.initTable(table, operName);
int row = baseMapper.insert(table);
// 初始化 该表的列信息 并保存
if (row > 0) {
List<GenTableColumn> genTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName);
List<GenTableColumn> saveColumns = new ArrayList<>();
for (GenTableColumn column : genTableColumns) {
GenUtils.initColumnField(column, table);
saveColumns.add(column);
}
if (CollUtil.isNotEmpty(saveColumns)) {
genTableColumnMapper.insertBatch(saveColumns);
}
}
}
} catch (Exception e) {
throw new ServiceException("导入失败:" + e.getMessage());
}
}
GenUtils
代码生成工具类
点击展开
初始化表信息 GenUtils#initTable()
public static void initTable(GenTable genTable, String operName) {
genTable.setClassName(convertClassName(genTable.getTableName()));
genTable.setPackageName(GenConfig.getPackageName());
genTable.setModuleName(getModuleName(GenConfig.getPackageName()));
genTable.setBusinessName(getBusinessName(genTable.getTableName()));
genTable.setFunctionName(replaceText(genTable.getTableComment()));
genTable.setFunctionAuthor(GenConfig.getAuthor());
genTable.setCreateBy(operName);
}
初始化字段属性 GenUtils#initColumnField()
public static void initColumnField(GenTableColumn column, GenTable table) {
// 括号处理
String dataType = getDbType(column.getColumnType());
String columnName = column.getColumnName();
column.setTableId(table.getTableId());
column.setCreateBy(table.getCreateBy());
// 设置java字段名 (驼峰处理)
column.setJavaField(StringUtils.toCamelCase(columnName));
// 设置默认类型
column.setJavaType(GenConstants.TYPE_STRING);
// 设置默认查询条件
column.setQueryType(GenConstants.QUERY_EQ);
// 数据类型处理
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)) {
// 时间类型处理
column.setJavaType(GenConstants.TYPE_DATE);
column.setHtmlType(GenConstants.HTML_DATETIME);
} else if (arraysContains(GenConstants.COLUMNTYPE_NUMBER, dataType)) {
// 数值类型处理
column.setHtmlType(GenConstants.HTML_INPUT);
// 如果是浮点型 统一用BigDecimal
String[] str = StringUtils.split(StringUtils.substringBetween(column.getColumnType(), "(", ")"), StringUtils.SEPARATOR);
if (str != null && str.length == 2 && Integer.parseInt(str[1]) > 0) {
// 浮点型
column.setJavaType(GenConstants.TYPE_BIGDECIMAL);
} else if (str != null && str.length == 1 && Integer.parseInt(str[0]) <= 10) {
// 整型
column.setJavaType(GenConstants.TYPE_INTEGER);
} else {
// 长整型
column.setJavaType(GenConstants.TYPE_LONG);
}
}
// BO对象 默认插入勾选
if (!arraysContains(GenConstants.COLUMNNAME_NOT_ADD, columnName) && !column.isPk()) {
column.setIsInsert(GenConstants.REQUIRE);
}
// BO对象 默认编辑勾选
if (!arraysContains(GenConstants.COLUMNNAME_NOT_EDIT, columnName)) {
column.setIsEdit(GenConstants.REQUIRE);
}
// BO对象 默认是否必填勾选
if (!arraysContains(GenConstants.COLUMNNAME_NOT_EDIT, columnName)) {
column.setIsRequired(GenConstants.REQUIRE);
}
// VO对象 默认返回勾选
if (!arraysContains(GenConstants.COLUMNNAME_NOT_LIST, columnName)) {
column.setIsList(GenConstants.REQUIRE);
}
// BO对象 默认查询勾选
if (!arraysContains(GenConstants.COLUMNNAME_NOT_QUERY, columnName) && !column.isPk()) {
column.setIsQuery(GenConstants.REQUIRE);
}
// 固有字段控制
// 查询字段类型
if (StringUtils.endsWithIgnoreCase(columnName, "name")) {
column.setQueryType(GenConstants.QUERY_LIKE);
}
// 状态字段设置单选框
if (StringUtils.endsWithIgnoreCase(columnName, "status")) {
column.setHtmlType(GenConstants.HTML_RADIO);
}
// 类型&性别字段设置下拉框
else if (StringUtils.endsWithIgnoreCase(columnName, "type")
|| StringUtils.endsWithIgnoreCase(columnName, "sex")) {
column.setHtmlType(GenConstants.HTML_SELECT);
}
// 图片字段设置图片上传控件
else if (StringUtils.endsWithIgnoreCase(columnName, "image")) {
column.setHtmlType(GenConstants.HTML_IMAGE_UPLOAD);
}
// 文件字段设置文件上传控件
else if (StringUtils.endsWithIgnoreCase(columnName, "file")) {
column.setHtmlType(GenConstants.HTML_FILE_UPLOAD);
}
// 内容字段设置富文本控件
else if (StringUtils.endsWithIgnoreCase(columnName, "content")) {
column.setHtmlType(GenConstants.HTML_EDITOR);
}
}
Xml 核心SQL代码
库表信息搜索后并初始化
点击展开
获取表信息 , SQL执行语句 GenTableMapper.selectDbTableListByNames() (该方法适配不同数据源应用 , 只需关注MySQL应用方式即可)
<select id="selectDbTableListByNames" resultMap="GenTableResult">
<if test="@com.ruoyi.common.helper.DataBaseHelper@isMySql()">
select table_name, table_comment, create_time, update_time from information_schema.tables
where table_name NOT LIKE 'xxl_job_%' and table_name NOT LIKE 'gen_%' and table_schema = (select database())
and table_name in
<foreach collection="array" item="name" open="(" separator="," close=")">
#{name}
</foreach>
</if>
<if test="@com.ruoyi.common.helper.DataBaseHelper@isOracle()">
select lower(dt.table_name) as table_name, dtc.comments as table_comment, uo.created as create_time, uo.last_ddl_time as update_time
from user_tables dt, user_tab_comments dtc, user_objects uo
where dt.table_name = dtc.table_name
and dt.table_name = uo.object_name
and uo.object_type = 'TABLE'
AND dt.table_name NOT LIKE 'XXL_JOB_%' AND dt.table_name NOT LIKE 'GEN_%'
AND dt.table_name NOT IN (select table_name from gen_table)
and lower(dt.table_name) in
<foreach collection="array" item="name" open="(" separator="," close=")">
#{name}
</foreach>
</if>
<if test="@com.ruoyi.common.helper.DataBaseHelper@isPostgerSql()">
select table_name, table_comment, create_time, update_time
from (
SELECT c.relname AS table_name,
obj_description(c.oid) AS table_comment,
CURRENT_TIMESTAMP AS create_time,
CURRENT_TIMESTAMP AS update_time
FROM pg_class c
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE (c.relkind = ANY (ARRAY ['r'::"char", 'p'::"char"]))
AND c.relname != 'spatial_%'::text
AND n.nspname = 'public'::name
AND n.nspname <![CDATA[ <> ]]> ''::name
) list_table
where table_name NOT LIKE 'xxl_job_%' and table_name NOT LIKE 'gen_%'
and table_name in
<foreach collection="array" item="name" open="(" separator="," close=")">
#{name}
</foreach>
</if>
<if test="@com.ruoyi.common.helper.DataBaseHelper@isSqlServer()">
SELECT cast(D.NAME as nvarchar) as table_name,
cast(F.VALUE as nvarchar) as table_comment,
crdate as create_time,
refdate as update_time
FROM SYSOBJECTS D
INNER JOIN SYS.EXTENDED_PROPERTIES F ON D.ID = F.MAJOR_ID
AND F.MINOR_ID = 0 AND D.XTYPE = 'U' AND D.NAME != 'DTPROPERTIES'
AND D.NAME NOT LIKE 'xxl_job_%' AND D.NAME NOT LIKE 'gen_%'
AND D.NAME in
<foreach collection="array" item="name" open="(" separator="," close=")">
#{name}
</foreach>
</if>
</select>
实际执行SQL (用法和上面一样)
SELECT
table_name,
table_comment,
create_time,
update_time
FROM
information_schema.TABLES
WHERE
table_name NOT LIKE 'xxl_job_%'
AND table_name NOT LIKE 'gen_%'
AND table_schema = (SELECT DATABASE())
# 多个表名逗号分隔
AND table_name IN ( 'tableName' )
获取表字段信息 , SQL执行语句 GenTableColumnMapper.selectDbTableColumnsByName()
<select id="selectDbTableColumnsByName" parameterType="String" resultMap="GenTableColumnResult">
<if test="@com.ruoyi.common.helper.DataBaseHelper@isMySql()">
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
</if>
<if test="@com.ruoyi.common.helper.DataBaseHelper@isOracle()">
select lower(temp.column_name) as column_name,
(case when (temp.nullable = 'N' and temp.constraint_type != 'P') then '1' else '0' end) as is_required,
(case when temp.constraint_type = 'P' then '1' else '0' end) as is_pk,
temp.column_id as sort,
temp.comments as column_comment,
(case when temp.constraint_type = 'P' then '1' else '0' end) as is_increment,
lower(temp.data_type) as column_type
from (
select col.column_id, col.column_name,col.nullable, col.data_type, colc.comments, uc.constraint_type, row_number()
over (partition by col.column_name order by uc.constraint_type desc) as row_flg
from user_tab_columns col
left join user_col_comments colc on colc.table_name = col.table_name and colc.column_name = col.column_name
left join user_cons_columns ucc on ucc.table_name = col.table_name and ucc.column_name = col.column_name
left join user_constraints uc on uc.constraint_name = ucc.constraint_name
where col.table_name = upper(#{tableName})
) temp
WHERE temp.row_flg = 1
ORDER BY temp.column_id
</if>
<if test="@com.ruoyi.common.helper.DataBaseHelper@isPostgerSql()">
SELECT column_name, is_required, is_pk, sort, column_comment, is_increment, column_type
FROM (
SELECT c.relname AS table_name,
a.attname AS column_name,
d.description AS column_comment,
CASE WHEN a.attnotnull AND con.conname IS NULL THEN 1 ELSE 0
END AS is_required,
CASE WHEN con.conname IS NOT NULL THEN 1 ELSE 0
END AS is_pk,
a.attnum AS sort,
CASE WHEN "position"(pg_get_expr(ad.adbin, ad.adrelid),
((c.relname::text || '_'::text) || a.attname::text) || '_seq'::text) > 0 THEN 1 ELSE 0
END AS is_increment,
btrim(
CASE WHEN t.typelem <![CDATA[ <> ]]> 0::oid AND t.typlen = '-1'::integer THEN 'ARRAY'::text ELSE
CASE WHEN t.typtype = 'd'::"char" THEN format_type(t.typbasetype, NULL::integer)
ELSE format_type(a.atttypid, NULL::integer) END
END, '"'::text
) AS column_type
FROM pg_attribute a
JOIN (pg_class c JOIN pg_namespace n ON c.relnamespace = n.oid) ON a.attrelid = c.oid
LEFT JOIN pg_description d ON d.objoid = c.oid AND a.attnum = d.objsubid
LEFT JOIN pg_constraint con ON con.conrelid = c.oid AND (a.attnum = ANY (con.conkey))
LEFT JOIN pg_attrdef ad ON a.attrelid = ad.adrelid AND a.attnum = ad.adnum
LEFT JOIN pg_type t ON a.atttypid = t.oid
WHERE (c.relkind = ANY (ARRAY ['r'::"char", 'p'::"char"]))
AND a.attnum > 0
AND n.nspname = 'public'::name
ORDER BY c.relname, a.attnum
) temp
WHERE table_name = (#{tableName})
AND column_type <![CDATA[ <> ]]> '-'
</if>
<if test="@com.ruoyi.common.helper.DataBaseHelper@isSqlServer()">
SELECT
cast(A.NAME as nvarchar) as column_name,
cast(B.NAME as nvarchar) + (case when B.NAME = 'numeric' then '(' + cast(A.prec as nvarchar) + ',' + cast(A.scale as nvarchar) + ')' else '' end) as column_type,
cast(G.[VALUE] as nvarchar) as column_comment,
(SELECT 1 FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE Z WHERE TABLE_NAME = D.NAME and A.NAME = Z.column_name ) as is_pk,
colorder as sort
FROM SYSCOLUMNS A
LEFT JOIN SYSTYPES B ON A.XTYPE = B.XUSERTYPE
INNER JOIN SYSOBJECTS D ON A.ID = D.ID AND D.XTYPE='U' AND D.NAME != 'DTPROPERTIES'
LEFT JOIN SYS.EXTENDED_PROPERTIES G ON A.ID = G.MAJOR_ID AND A.COLID = G.MINOR_ID
LEFT JOIN SYS.EXTENDED_PROPERTIES F ON D.ID = F.MAJOR_ID AND F.MINOR_ID = 0
WHERE D.NAME = #{tableName}
ORDER BY A.COLORDER
</if>
</select>
实际执行SQL
SELECT
column_name,
# 判断列是否必要的 (为空并且不是主键)
( CASE WHEN ( is_nullable = 'no' && 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 = ( 'paper_test' )
ORDER BY
ordinal_position
# 详细生成表
修改时需要单表的相关详细数据
获取库表基础信息 GenController#getInfo()
@SaCheckPermission("tool:gen:query")
@GetMapping(value = "/{tableId}")
public R<Map<String, Object>> getInfo(@PathVariable Long tableId) {
GenTable table = genTableService.selectGenTableById(tableId);
List<GenTable> tables = genTableService.selectGenTableAll();
// 左查询 gen_column
List<GenTableColumn> list = genTableService.selectGenTableColumnListByTableId(tableId);
Map<String, Object> map = new HashMap<String, Object>();
// 当前表详细
map.put("info", table);
// 当前表字段信息
map.put("rows", list);
// 所有表信息 , 关联表设置别用 (目前尚未开放可以无视)
map.put("tables", tables);
return R.ok(map);
}
# 修改生成表
修改表信息接口 GenController#editSave()
@SaCheckPermission("tool:gen:edit")
@Log(title = "代码生成", businessType = BusinessType.UPDATE)
@PutMapping
public R<Void> editSave(@Validated @RequestBody GenTable genTable) {
// 校验数据
genTableService.validateEdit(genTable);
genTableService.updateGenTable(genTable);
return R.ok();
}
修改实现 GenTableServiceImpl#updateGenTable()
@Transactional(rollbackFor = Exception.class)
@Override
public void updateGenTable(GenTable genTable) {
String options = JsonUtils.toJsonString(genTable.getParams());
genTable.setOptions(options);
// 保存修改表信息
int row = baseMapper.updateById(genTable);
// 保存修改列信息
if (row > 0) {
for (GenTableColumn cenTableColumn : genTable.getColumns()) {
genTableColumnMapper.updateById(cenTableColumn);
}
}
}
# 生成预览
预览接口 GenController#preview()
@SaCheckPermission("tool:gen:preview")
@GetMapping("/preview/{tableId}")
public R<Map<String, String>> preview(@PathVariable("tableId") Long tableId) throws IOException {
Map<String, String> dataMap = genTableService.previewCode(tableId);
return R.ok(dataMap);
}
导出具体实现 GenTableServiceImpl#previewCode()
具体填充的数据 , 点击跳转
@Override
public Map<String, String> previewCode(Long tableId) {
Map<String, String> dataMap = new LinkedHashMap<>();
// 查询表信息
GenTable table = baseMapper.selectGenTableById(tableId);
List<Long> menuIds = new ArrayList<>();
// 计算雪花id为生成SQL语句准备的
for (int i = 0; i < 6; i++) {
menuIds.add(identifierGenerator.nextId(null).longValue());
}
table.setMenuIds(menuIds);
// 设置主子表信息 (在库获取设置)
setSubTable(table);
// 设置主键列信息
setPkColumn(table);
// 初始化 .vm解析
VelocityInitializer.initVelocity();
// 构建模板上下文(填充数据)
VelocityContext context = VelocityUtils.prepareContext(table);
// 获取模板列表
List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory());
for (String template : templates) {
// 渲染模板
StringWriter sw = new StringWriter();
Template tpl = Velocity.getTemplate(template, Constants.UTF8);
tpl.merge(context, sw);
dataMap.put(template, sw.toString());
}
return dataMap;
}
# 生成代码
生成方式有两种
- 下载zip (推荐)
- 自定义路径生成
# 下载zip
zip下载接口 GenController#download()
@SaCheckPermission("tool:gen:code")
@Log(title = "代码生成", businessType = BusinessType.GENCODE)
@GetMapping("/download/{tableName}")
public void download(HttpServletResponse response, @PathVariable("tableName") String tableName) throws IOException {
// 压缩包流
byte[] data = genTableService.downloadCode(tableName);
genCode(response, data);
}
// ...
private void genCode(HttpServletResponse response, byte[] data) throws IOException {
response.reset();
response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
response.setHeader("Content-Disposition", "attachment; filename=\"ruoyi.zip\"");
response.addHeader("Content-Length", "" + data.length);
response.setContentType("application/octet-stream; charset=UTF-8");
IoUtil.write(response.getOutputStream(), false, data);
}
业务下载接口 GenTableServiceImpl#downloadCode()
@Override
public byte[] downloadCode(String[] tableNames) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ZipOutputStream zip = new ZipOutputStream(outputStream);
for (String tableName : tableNames) {
generatorCode(tableName, zip);
}
IoUtil.close(zip);
return outputStream.toByteArray();
}
// ...
// 和生成预览使用方式一样 , 该方法是将代码写入压缩流
private void generatorCode(String tableName, ZipOutputStream zip) {
// 查询表信息
GenTable table = baseMapper.selectGenTableByName(tableName);
List<Long> menuIds = new ArrayList<>();
for (int i = 0; i < 6; i++) {
menuIds.add(identifierGenerator.nextId(null).longValue());
}
table.setMenuIds(menuIds);
// 设置主子表信息
setSubTable(table);
// 设置主键列信息
setPkColumn(table);
// 初始化 .vm解析
VelocityInitializer.initVelocity();
// 构建模板上下文(填充数据)
VelocityContext context = VelocityUtils.prepareContext(table);
// 获取模板列表
List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory());
for (String template : templates) {
// 渲染模板
StringWriter sw = new StringWriter();
Template tpl = Velocity.getTemplate(template, Constants.UTF8);
tpl.merge(context, sw);
try {
// 添加到zip
zip.putNextEntry(new ZipEntry(VelocityUtils.getFileName(template, table)));
IoUtil.write(zip, StandardCharsets.UTF_8, false, sw.toString());
IoUtil.close(sw);
zip.flush();
zip.closeEntry();
} catch (IOException e) {
log.error("渲染模板失败,表名:" + table.getTableName(), e);
}
}
}
# 自定义路径生成
自定义路径 GenController#genCode()
@SaCheckPermission("tool:gen:code")
@Log(title = "代码生成", businessType = BusinessType.GENCODE)
@GetMapping("/genCode/{tableName}")
public R<Void> genCode(@PathVariable("tableName") String tableName) {
genTableService.generatorCode(tableName);
return R.ok();
}
业务下载接口 GenTableServiceImpl#downloadCode()
@Override
public void generatorCode(String tableName) {
// 查询表信息
GenTable table = baseMapper.selectGenTableByName(tableName);
// 设置主子表信息
setSubTable(table);
// 设置主键列信息
setPkColumn(table);
// 初始化 .vm解析
VelocityInitializer.initVelocity();
// 构建模板上下文(填充数据)
VelocityContext context = VelocityUtils.prepareContext(table);
// 获取模板列表
List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory());
for (String template : templates) {
// 排除前端相关代码
if (!StringUtils.containsAny(template, "sql.vm", "api.js.vm", "index.vue.vm", "index-tree.vue.vm")) {
// 渲染模板
StringWriter sw = new StringWriter();
Template tpl = Velocity.getTemplate(template, Constants.UTF8);
tpl.merge(context, sw);
try {
// 获取自定义目录
String path = getGenPath(table, template);
// 写入自定义目录的文件中
FileUtils.writeUtf8String(sw.toString(), path);
} catch (Exception e) {
throw new ServiceException("渲染模板失败,表名:" + table.getTableName());
}
}
}
}
// ...
public static String getGenPath(GenTable table, String template) {
String genPath = table.getGenPath();
if (StringUtils.equals(genPath, "/")) {
return System.getProperty("user.dir") + File.separator + "src" + File.separator + VelocityUtils.getFileName(template, table);
}
return genPath + File.separator + VelocityUtils.getFileName(template, table);
}
# 同步生成表
同步接口 GenController#synchDb()
@SaCheckPermission("tool:gen:edit")
@Log(title = "代码生成", businessType = BusinessType.UPDATE)
@GetMapping("/synchDb/{tableName}")
public R<Void> synchDb(@PathVariable("tableName") String tableName) {
genTableService.synchDb(tableName);
return R.ok();
}
业务实现 GenTableServiceImpl#synchDb()
public void synchDb(String tableName) {
GenTable table = baseMapper.selectGenTableByName(tableName);
List<GenTableColumn> tableColumns = table.getColumns();
// Map转化 , key 为 column_name
Map<String, GenTableColumn> tableColumnMap = StreamUtils.toIdentityMap(tableColumns, GenTableColumn::getColumnName);
// 查库判断存在
List<GenTableColumn> dbTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName);
if (CollUtil.isEmpty(dbTableColumns)) {
throw new ServiceException("同步数据失败,原表结构不存在");
}
// 拿到表中的所有字段名
List<String> dbTableColumnNames = StreamUtils.toList(dbTableColumns, GenTableColumn::getColumnName);
List<GenTableColumn> saveColumns = new ArrayList<>();
dbTableColumns.forEach(column -> {
// 初始化字段
GenUtils.initColumnField(column, table);
// Map匹配存在字段 (保留原表信息操作)
if (tableColumnMap.containsKey(column.getColumnName())) {
GenTableColumn prevColumn = tableColumnMap.get(column.getColumnName());
column.setColumnId(prevColumn.getColumnId());
if (column.isList()) {
// 如果是列表,继续保留查询方式/字典类型选项
column.setDictType(prevColumn.getDictType());
column.setQueryType(prevColumn.getQueryType());
}
// 如果列是必填且非忽略及父属性,并且在新增/修改中,且是非主键列,则保留之前的必填/显示类型选项
if (StringUtils.isNotEmpty(prevColumn.getIsRequired()) && !column.isPk()
&& (column.isInsert() || column.isEdit())
&& ((column.isUsableColumn()) || (!column.isSuperColumn()))) {
// 如果是(新增/修改&非主键/非忽略及父属性),继续保留必填/显示类型选项
column.setIsRequired(prevColumn.getIsRequired());
column.setHtmlType(prevColumn.getHtmlType());
}
}
saveColumns.add(column);
});
if (CollUtil.isNotEmpty(saveColumns)) {
// 批量更新
genTableColumnMapper.insertOrUpdateBatch(saveColumns);
}
// 删除多余的字段 (将新表不包含的字段进行删除)
List<GenTableColumn> delColumns = StreamUtils.filter(tableColumns, column ->
!dbTableColumnNames.contains(column.getColumnName()));
if (CollUtil.isNotEmpty(delColumns)) {
List<Long> ids = StreamUtils.toList(delColumns, GenTableColumn::getColumnId);
genTableColumnMapper.deleteBatchIds(ids);
}
}
# 上下文参数&模板
模板仅在代码当中注释补充展示
# 上下文参数
通用上下文参数
上下文参数 | 说明 |
---|---|
author | 作者名 |
BusinessName | 生成业务名 , 驼峰处理 |
businessName | 生成业务名 , 无驼峰 |
basePackage | 包前缀 |
ClassName | 类名 , 驼峰处理 |
className | 类名 , 无驼峰 |
columns | 表所有列字段 |
dicts | 字典组 (包含有下拉框 , 单选框 , 复选框和字典名) |
datetime | 生成时间 |
functionName | 模块描述 , 功能名 |
importList | 外部引列列表 |
moduleName | 模块名 |
packageName | 包路径 |
permissionPrefix | 权限前缀标识 (模块名:业务名) |
pkColumn | 主键字段对象 |
tplCategory | 模板类型 (单表 , 树表 , sub主子表) |
table | 表对象 |
tableName | 表名 |
# Java模板
实体对象 vm/java/domain.java.vm
点击展开
package ${packageName}.domain;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.Date;
import java.math.BigDecimal;
#foreach ($import in $importList)
import ${import};
#end
#if($table.crud || $table.sub)
import com.ruoyi.common.core.domain.BaseEntity;
#elseif($table.tree)
import com.ruoyi.common.core.domain.TreeEntity;
#end
/**
* ${functionName}对象 ${tableName}
*
* @author ${author}
* @date ${datetime}
*/
#if($table.crud || $table.sub)
#set($Entity="BaseEntity")
#elseif($table.tree)
#set($Entity="TreeEntity<${ClassName}>")
#end
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("${tableName}")
public class ${ClassName} extends ${Entity} {
private static final long serialVersionUID=1L;
#foreach ($column in $columns)
## 方法排除基类Entity字段
#if(!$table.isSuperColumn($column.javaField))
/**
* $column.columnComment
*/
## 根据属性标识添加注解
#if($column.javaField=='delFlag')
@TableLogic
#end
#if($column.javaField=='version')
@Version
#end
#if($column.pk)
@TableId(value = "$column.columnName")
#end
private $column.javaType $column.javaField;
#end
#end
}
请求响应类 vm/java/vo.java.vm
点击展开
package ${packageName}.domain.vo;
#foreach ($import in $importList)
import ${import};
#end
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.ruoyi.common.annotation.ExcelDictFormat;
import com.ruoyi.common.convert.ExcelDictConvert;
import lombok.Data;
import java.util.Date;
import java.io.Serializable;
/**
* ${functionName}视图对象 ${tableName}
*
* @author ${author}
* @date ${datetime}
*/
@Data
@ExcelIgnoreUnannotated
public class ${ClassName}Vo implements Serializable {
private static final long serialVersionUID = 1L;
#foreach ($column in $columns)
#if($column.list)
/**
* $column.columnComment
*/
## 字段内容获取括号中了 , 如果没有则直接显示
#set($parentheseIndex=$column.columnComment.indexOf("("))
#if($parentheseIndex != -1)
#set($comment=$column.columnComment.substring(0, $parentheseIndex))
#else
#set($comment=$column.columnComment)
#end
## 导出表格处理
#if(${column.dictType} && ${column.dictType} != '')
## 为字典类型 转化处理
@ExcelProperty(value = "${comment}" , converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "${column.dictType}" )
#elseif($parentheseIndex != -1)
## 为字典类型处理 (特殊转化处理)
@ExcelProperty(value = "${comment}" , converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "$column.readConverterExp()" )
#else
## 默认 导出不处理 仅做标识
@ExcelProperty(value = "${comment}" )
#end
private $column.javaType $column.javaField;
#end
#end
}
请求接收类 vm/java/bo.java.vm
点击展开
package ${packageName}.domain.bo;
import com.ruoyi.common.core.validate.AddGroup;
import com.ruoyi.common.core.validate.EditGroup;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.*;
import java.util.Date;
#foreach ($import in $importList)
import ${import};
#end
#if($table.crud || $table.sub)
import com.ruoyi.common.core.domain.BaseEntity;
#elseif($table.tree)
import com.ruoyi.common.core.domain.TreeEntity;
#end
/**
* ${functionName}业务对象 ${tableName}
*
* @author ${author}
* @date ${datetime}
*/
#if($table.crud || $table.sub)
#set($Entity="BaseEntity")
#elseif($table.tree)
#set($Entity="TreeEntity<${ClassName}Bo>")
#end
@Data
@EqualsAndHashCode(callSuper = true)
public class ${ClassName}Bo extends ${Entity} {
#foreach ($column in $columns)
## 额外判断请求参数非空处理
#if(!$table.isSuperColumn($column.javaField) && ($column.query || $column.insert || $column.edit))
/**
* $column.columnComment
*/
## 判断含有的操作组控制非空校验
#if($column.insert && $column.edit)
#set($Group="AddGroup.class, EditGroup.class")
#elseif($column.insert)
#set($Group="AddGroup.class")
#elseif($column.edit)
#set($Group="EditGroup.class")
#end
#if($column.required)
## 区分对象字符串处理
#if($column.javaType == 'String')
@NotBlank(message = "$column.columnComment不能为空" , groups = { $Group })
#else
@NotNull(message = "$column.columnComment不能为空" , groups = { $Group })
#end
#end
private $column.javaType $column.javaField;
#end
#end
}
业务接口 vm/java/service.java.vm (无核心业务代码)
点击展开
package ${packageName}.service;
import ${packageName}.domain.${ClassName};
import ${packageName}.domain.vo.${ClassName}Vo;
import ${packageName}.domain.bo.${ClassName}Bo;
#if($table.crud || $table.sub)
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
#end
import java.util.Collection;
import java.util.List;
/**
* ${functionName}Service接口
*
* @author ${author}
* @date ${datetime}
*/
public interface I${ClassName}Service {
/**
* 查询${functionName}
*/
${ClassName}Vo queryById(${pkColumn.javaType} ${pkColumn.javaField});
#if($table.crud || $table.sub)
/**
* 查询${functionName}列表
*/
TableDataInfo<${ClassName}Vo> queryPageList(${ClassName}Bo bo, PageQuery pageQuery);
#end
/**
* 查询${functionName}列表
*/
List<${ClassName}Vo> queryList(${ClassName}Bo bo);
/**
* 新增${functionName}
*/
Boolean insertByBo(${ClassName}Bo bo);
/**
* 修改${functionName}
*/
Boolean updateByBo(${ClassName}Bo bo);
/**
* 校验并批量删除${functionName}信息
*/
Boolean deleteWithValidByIds(Collection<${pkColumn.javaType}> ids, Boolean isValid);
}
业务实现类 vm/java/serviceImpl.java.vm
点击展开
主要业务还嘚是 buildQueryWrapper()方法 , 约束查询的构建
package ${packageName}.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.ruoyi.common.utils.StringUtils;
#if($table.crud || $table.sub)
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
#end
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import ${packageName}.domain.bo.${ClassName}Bo;
import ${packageName}.domain.vo.${ClassName}Vo;
import ${packageName}.domain.${ClassName};
import ${packageName}.mapper.${ClassName}Mapper;
import ${packageName}.service.I${ClassName}Service;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* ${functionName}Service业务层处理
*
* @author ${author}
* @date ${datetime}
*/
@RequiredArgsConstructor
@Service
public class ${ClassName}ServiceImpl implements I${ClassName}Service {
private final ${ClassName}Mapper baseMapper;
/**
* 查询${functionName}
*/
@Override
public ${ClassName}Vo queryById(${pkColumn.javaType} ${pkColumn.javaField}) {
return baseMapper.selectVoById(${pkColumn.javaField});
}
#if($table.crud || $table.sub)
/**
* 查询${functionName}列表
*/
@Override
public TableDataInfo<${ClassName}Vo> queryPageList(${ClassName}Bo bo, PageQuery pageQuery) {
LambdaQueryWrapper<${ClassName}> lqw = buildQueryWrapper(bo);
Page<${ClassName}Vo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
#end
/**
* 查询${functionName}列表
*/
@Override
public List<${ClassName}Vo> queryList(${ClassName}Bo bo) {
LambdaQueryWrapper<${ClassName}> lqw = buildQueryWrapper(bo); return baseMapper.selectVoList(lqw);
}
## 构建查询条件
private LambdaQueryWrapper<${ClassName}> buildQueryWrapper(${ClassName}Bo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<${ClassName}> lqw = Wrappers.lambdaQuery();
#foreach($column in $columns)
#if($column.query)
#set($queryType=$column.queryType)
#set($javaField=$column.javaField)
#set($javaType=$column.javaType)
#set($columnName=$column.columnName)
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
#set($mpMethod=$column.queryType.toLowerCase())
#if($queryType != 'BETWEEN')
## 查询判空
#if($javaType == 'String')
#set($condition='StringUtils.isNotBlank(bo.get'+$AttrName+'())')
#else
#set($condition='bo.get'+$AttrName+'() != null')
#end
lqw.$mpMethod($condition, ${ClassName}::get$AttrName, bo.get$AttrName());
#else
## 日期范围单独处理
lqw.between(params.get("begin$AttrName" ) != null && params.get("end$AttrName" ) != null,
${ClassName}::get$AttrName , params.get("begin$AttrName" ), params.get("end$AttrName" ));
#end
#end
#end
return lqw;
}
/**
* 新增${functionName}
*/
@Override
public Boolean insertByBo(${ClassName}Bo bo) {
${ClassName} add = BeanUtil.toBean(bo, ${ClassName}. class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
#set($pk=$pkColumn.javaField.substring(0,1).toUpperCase() + ${pkColumn.javaField.substring(1)})
if (flag) {
bo.set$pk(add.get$pk());
}
return flag;
}
/**
* 修改${functionName}
*/
@Override
public Boolean updateByBo(${ClassName}Bo bo) {
${ClassName} update = BeanUtil.toBean(bo, ${ClassName}. class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(${ClassName} entity) {
//TODO 做一些数据校验,如唯一约束
}
/**
* 批量删除${functionName}
*/
@Override
public Boolean deleteWithValidByIds(Collection<${pkColumn.javaType}> ids, Boolean isValid) {
if (isValid) {
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteBatchIds(ids) > 0;
}
}
vm/java/controller.java.vm (无核心业务代码)
点击展开
package ${packageName}.controller;
import java.util.List;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import lombok.RequiredArgsConstructor;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.validate.AddGroup;
import com.ruoyi.common.core.validate.EditGroup;
import com.ruoyi.common.core.validate.QueryGroup;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import ${packageName}.domain.vo.${ClassName}Vo;
import ${packageName}.domain.bo.${ClassName}Bo;
import ${packageName}.service.I${ClassName}Service;
#if($table.crud || $table.sub)
import com.ruoyi.common.core.page.TableDataInfo;
#elseif($table.tree)
#end
/**
* ${functionName}
*
* @author ${author}
* @date ${datetime}
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/${moduleName}/${businessName}" )
public class ${ClassName}Controller extends BaseController {
private final I${ClassName}Service i${ClassName}Service;
/**
* 查询${functionName}列表
*/
@SaCheckPermission("${permissionPrefix}:list" )
@GetMapping("/list" )
#if($table.crud || $table.sub)
public TableDataInfo<${ClassName}Vo> list(${ClassName}Bo bo, PageQuery pageQuery) {
return i${ClassName}Service.queryPageList(bo, pageQuery);
}
#elseif($table.tree)
public R<List<${ClassName}Vo>> list(${ClassName}Bo bo) {
List<${ClassName}Vo> list = i${ClassName}Service.queryList(bo);
return R.ok(list);
}
#end
/**
* 导出${functionName}列表
*/
@SaCheckPermission("${permissionPrefix}:export" )
@Log(title = "${functionName}" , businessType = BusinessType.EXPORT)
@PostMapping("/export" )
public void export(${ClassName}Bo bo, HttpServletResponse response) {
List<${ClassName}Vo> list = i${ClassName}Service.queryList(bo);
ExcelUtil.exportExcel(list, "${functionName}" , ${ClassName}Vo.class, response);
}
/**
* 获取${functionName}详细信息
*
* @param ${pkColumn.javaField} 主键
*/
@SaCheckPermission("${permissionPrefix}:query" )
@GetMapping("/{${pkColumn.javaField}}" )
public R<${ClassName}Vo> getInfo(@NotNull(message = "主键不能为空" ) @PathVariable ${pkColumn.javaType} ${pkColumn.javaField}) {
return R.ok(i${ClassName}Service.queryById(${pkColumn.javaField}));
}
/**
* 新增${functionName}
*/
@SaCheckPermission("${permissionPrefix}:add" )
@Log(title = "${functionName}" , businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody ${ClassName}Bo bo) {
return toAjax(i${ClassName}Service.insertByBo(bo));
}
/**
* 修改${functionName}
*/
@SaCheckPermission("${permissionPrefix}:edit" )
@Log(title = "${functionName}" , businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody ${ClassName}Bo bo) {
return toAjax(i${ClassName}Service.updateByBo(bo));
}
/**
* 删除${functionName}
*
* @param ${pkColumn.javaField}s 主键串
*/
@SaCheckPermission("${permissionPrefix}:remove" )
@Log(title = "${functionName}" , businessType = BusinessType.DELETE)
@DeleteMapping("/{${pkColumn.javaField}s}" )
public R<Void> remove(@NotEmpty(message = "主键不能为空" ) @PathVariable ${pkColumn.javaType}[] ${pkColumn.javaField}s) {
return toAjax(i${ClassName}Service.deleteWithValidByIds(Arrays.asList(${pkColumn.javaField}s), true));
}
}
# XML模块
vm/java/mapper.java.vm (无核心业务代码)
点击展开
package ${packageName}.mapper;
import ${packageName}.domain.${ClassName};
import ${packageName}.domain.vo.${ClassName}Vo;
import com.ruoyi.common.core.mapper.BaseMapperPlus;
/**
* ${functionName}Mapper接口
*
* @author ${author}
* @date ${datetime}
*/
public interface ${ClassName}Mapper extends BaseMapperPlus<${ClassName}Mapper, ${ClassName}, ${ClassName}Vo> {
}
vm/xml/mapper.xml.vm (无核心业务代码)
点击展开
<?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="${packageName}.mapper.${ClassName}Mapper">
<resultMap type="${packageName}.domain.${ClassName}" id="${ClassName}Result">
#foreach ($column in $columns)
<result property="${column.javaField}" column="${column.columnName}"/>
#end
</resultMap>
</mapper>
# SQL模板
vm/sql/sql.vm
点击展开
-- 菜单 SQL
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values(${table.menuIds[0]}, '${functionName}', '${parentMenuId}', '1', '${businessName}', '${moduleName}/${businessName}/index', 1, 0, 'C', '0', '0', '${permissionPrefix}:list', '#', 'admin', sysdate(), '', null, '${functionName}菜单');
-- 按钮 SQL
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values(${table.menuIds[1]}, '${functionName}查询', ${table.menuIds[0]}, '1', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:query', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values(${table.menuIds[2]}, '${functionName}新增', ${table.menuIds[0]}, '2', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:add', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values(${table.menuIds[3]}, '${functionName}修改', ${table.menuIds[0]}, '3', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:edit', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values(${table.menuIds[4]}, '${functionName}删除', ${table.menuIds[0]}, '4', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:remove', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values(${table.menuIds[5]}, '${functionName}导出', ${table.menuIds[0]}, '5', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:export', '#', 'admin', sysdate(), '', null, '');
其他数据源无关键逻辑代码省略..