feat(MybatisMapperBatchOpRender): 实现Mybatis批量操作XML生成器
- 添加StrUtil和BadRequestException依赖导入 - 增加TableName注解支持验证实体类有效性 - 实现批量插入、更新、删除XML模板生成功能 - 添加字段过滤逻辑排除serialVersionUID - 实现主键字段验证和参数校验功能 - 生成标准的Mybatis批量操作SQL映射XML - 支持下划线命名转换和动态字段映射 - 提供完整的批量操作接口方法声明生成
This commit is contained in:
+118
@@ -0,0 +1,118 @@
|
|||||||
|
package cn.odboy;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.odboy.framework.exception.BadRequestException;
|
||||||
|
import cn.odboy.system.dal.dataobject.SystemDeptTb;
|
||||||
|
import cn.odboy.util.KitClassUtil;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mybatis批量操作生成器
|
||||||
|
*
|
||||||
|
* @author odboy
|
||||||
|
*/
|
||||||
|
public class MybatisMapperBatchOpRender {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渲染MapperXml
|
||||||
|
*
|
||||||
|
* @param entityClass 持久类
|
||||||
|
* @param primaryKeyName 主键名称
|
||||||
|
*/
|
||||||
|
public <T, K> void render(Class<?> entityClass, String primaryKeyName) {
|
||||||
|
if (entityClass == null) {
|
||||||
|
throw new BadRequestException("参数 entityClass 必填");
|
||||||
|
}
|
||||||
|
TableName tableNameAnnotation = entityClass.getAnnotation(TableName.class);
|
||||||
|
if (tableNameAnnotation == null) {
|
||||||
|
throw new BadRequestException("参数 entityClass 不是一个有效的Mybatis表对象");
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Field> fields = new ArrayList<>();
|
||||||
|
KitClassUtil.getAllFields(entityClass, fields);
|
||||||
|
fields = fields.stream().filter(f -> !"serialVersionUID".equals(f.getName())).collect(Collectors.toList());
|
||||||
|
|
||||||
|
Field primaryKeyField = fields.stream().filter(f -> f.getName().equals(primaryKeyName)).findFirst().orElse(null);
|
||||||
|
if (primaryKeyField == null) {
|
||||||
|
throw new BadRequestException("参数 primaryKeyName 设置有误");
|
||||||
|
}
|
||||||
|
|
||||||
|
fields = fields.stream().filter(f -> !f.getName().equals(primaryKeyName)).collect(Collectors.toList());
|
||||||
|
|
||||||
|
// 持久类主键类型名
|
||||||
|
String entityPkTypeName = primaryKeyField.getType().getSimpleName();
|
||||||
|
// 持久类名
|
||||||
|
String entityClassName = entityClass.getSimpleName();
|
||||||
|
// 数据表名
|
||||||
|
String tableName = tableNameAnnotation.value();
|
||||||
|
|
||||||
|
System.err.println("============== 渲染Mapper ==================");
|
||||||
|
String mapperBatchInsert = "void batchInsert(@Param(\"list\") List<$EntityClassName> list);";
|
||||||
|
System.err.println(mapperBatchInsert.replace("$EntityClassName", entityClassName));
|
||||||
|
String mapperBatchUpdate = "void batchUpdateById(@Param(\"list\") List<$EntityClassName> list);";
|
||||||
|
System.err.println(mapperBatchUpdate.replace("$EntityClassName", entityClassName));
|
||||||
|
String mapperBatchDelete = "void batchDeleteByIds(@Param(\"list\") List<$EntityPkTypeName> list);";
|
||||||
|
System.err.println(mapperBatchDelete.replace("$EntityPkTypeName", entityPkTypeName));
|
||||||
|
System.err.println("\n============== 渲染MapperXml ==================");
|
||||||
|
List<String> fieldNameList = new ArrayList<>();
|
||||||
|
List<String> fieldNameUnderlineList = new ArrayList<>();
|
||||||
|
List<String> fieldNameItemList = new ArrayList<>();
|
||||||
|
|
||||||
|
for (Field field : fields) {
|
||||||
|
fieldNameList.add(field.getName());
|
||||||
|
}
|
||||||
|
for (String fieldName : fieldNameList) {
|
||||||
|
fieldNameUnderlineList.add(StrUtil.toUnderlineCase(fieldName));
|
||||||
|
fieldNameItemList.add("#{item." + fieldName + "}");
|
||||||
|
}
|
||||||
|
|
||||||
|
String batchInsertXml = "<insert id=\"batchInsert\">\n"
|
||||||
|
+ "INSERT INTO " + tableName + " ("
|
||||||
|
+ String.join(",", fieldNameUnderlineList)
|
||||||
|
+ ") VALUES\n"
|
||||||
|
+ "<foreach collection=\"list\" item=\"item\" separator=\",\">\n"
|
||||||
|
+ "(\n"
|
||||||
|
+ String.join(",\n", fieldNameItemList)
|
||||||
|
+ ")\n"
|
||||||
|
+ "</foreach>\n"
|
||||||
|
+ "</insert>\n";
|
||||||
|
System.err.println(batchInsertXml);
|
||||||
|
|
||||||
|
StringBuilder ifStringBuilder = new StringBuilder();
|
||||||
|
for (int i = 0; i < fieldNameList.size(); i++) {
|
||||||
|
ifStringBuilder.append("<if test=\"item.")
|
||||||
|
.append(fieldNameList.get(i))
|
||||||
|
.append(" != null\">")
|
||||||
|
.append(fieldNameUnderlineList.get(i))
|
||||||
|
.append(" = #{item.")
|
||||||
|
.append(fieldNameList.get(i))
|
||||||
|
.append("},</if>\n");
|
||||||
|
}
|
||||||
|
String batchUpdateXml = "<update id=\"batchUpdateById\">\n"
|
||||||
|
+ "<foreach collection=\"list\" item=\"item\" separator=\";\">\n"
|
||||||
|
+ "UPDATE " + tableName + "\n"
|
||||||
|
+ "<set>\n"
|
||||||
|
+ ifStringBuilder
|
||||||
|
+ "</set>\n"
|
||||||
|
+ "WHERE " + StrUtil.toUnderlineCase(primaryKeyName) + " = #{item." + primaryKeyName + "}\n"
|
||||||
|
+ "</foreach>\n"
|
||||||
|
+ "</update>\n";
|
||||||
|
System.err.println(batchUpdateXml);
|
||||||
|
|
||||||
|
String batchDeleteXml = "<delete id=\"batchDeleteByIds\">\n"
|
||||||
|
+ "delete from " + tableName + " where " + StrUtil.toUnderlineCase(primaryKeyName) + " in\n"
|
||||||
|
+ "<foreach collection=\"list\" item=\"id\" open=\"(\" close=\")\" separator=\",\">\n"
|
||||||
|
+ "#{id}\n"
|
||||||
|
+ "</foreach>\n"
|
||||||
|
+ "</delete>";
|
||||||
|
System.err.println(batchDeleteXml);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
new MybatisMapperBatchOpRender().render(SystemDeptTb.class, "id");
|
||||||
|
}
|
||||||
|
}
|
||||||
+118
@@ -0,0 +1,118 @@
|
|||||||
|
package cn.odboy;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.odboy.framework.exception.BadRequestException;
|
||||||
|
import cn.odboy.system.dal.dataobject.SystemDeptTb;
|
||||||
|
import cn.odboy.util.KitClassUtil;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mybatis批量操作生成器
|
||||||
|
*
|
||||||
|
* @author odboy
|
||||||
|
*/
|
||||||
|
public class MybatisMapperBatchOpRender {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渲染MapperXml
|
||||||
|
*
|
||||||
|
* @param entityClass 持久类
|
||||||
|
* @param primaryKeyName 主键名称
|
||||||
|
*/
|
||||||
|
public <T, K> void render(Class<?> entityClass, String primaryKeyName) {
|
||||||
|
if (entityClass == null) {
|
||||||
|
throw new BadRequestException("参数 entityClass 必填");
|
||||||
|
}
|
||||||
|
TableName tableNameAnnotation = entityClass.getAnnotation(TableName.class);
|
||||||
|
if (tableNameAnnotation == null) {
|
||||||
|
throw new BadRequestException("参数 entityClass 不是一个有效的Mybatis表对象");
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Field> fields = new ArrayList<>();
|
||||||
|
KitClassUtil.getAllFields(entityClass, fields);
|
||||||
|
fields = fields.stream().filter(f -> !"serialVersionUID".equals(f.getName())).collect(Collectors.toList());
|
||||||
|
|
||||||
|
Field primaryKeyField = fields.stream().filter(f -> f.getName().equals(primaryKeyName)).findFirst().orElse(null);
|
||||||
|
if (primaryKeyField == null) {
|
||||||
|
throw new BadRequestException("参数 primaryKeyName 设置有误");
|
||||||
|
}
|
||||||
|
|
||||||
|
fields = fields.stream().filter(f -> !f.getName().equals(primaryKeyName)).collect(Collectors.toList());
|
||||||
|
|
||||||
|
// 持久类主键类型名
|
||||||
|
String entityPkTypeName = primaryKeyField.getType().getSimpleName();
|
||||||
|
// 持久类名
|
||||||
|
String entityClassName = entityClass.getSimpleName();
|
||||||
|
// 数据表名
|
||||||
|
String tableName = tableNameAnnotation.value();
|
||||||
|
|
||||||
|
System.err.println("============== 渲染Mapper ==================");
|
||||||
|
String mapperBatchInsert = "void batchInsert(@Param(\"list\") List<$EntityClassName> list);";
|
||||||
|
System.err.println(mapperBatchInsert.replace("$EntityClassName", entityClassName));
|
||||||
|
String mapperBatchUpdate = "void batchUpdateById(@Param(\"list\") List<$EntityClassName> list);";
|
||||||
|
System.err.println(mapperBatchUpdate.replace("$EntityClassName", entityClassName));
|
||||||
|
String mapperBatchDelete = "void batchDeleteByIds(@Param(\"list\") List<$EntityPkTypeName> list);";
|
||||||
|
System.err.println(mapperBatchDelete.replace("$EntityPkTypeName", entityPkTypeName));
|
||||||
|
System.err.println("\n============== 渲染MapperXml ==================");
|
||||||
|
List<String> fieldNameList = new ArrayList<>();
|
||||||
|
List<String> fieldNameUnderlineList = new ArrayList<>();
|
||||||
|
List<String> fieldNameItemList = new ArrayList<>();
|
||||||
|
|
||||||
|
for (Field field : fields) {
|
||||||
|
fieldNameList.add(field.getName());
|
||||||
|
}
|
||||||
|
for (String fieldName : fieldNameList) {
|
||||||
|
fieldNameUnderlineList.add(StrUtil.toUnderlineCase(fieldName));
|
||||||
|
fieldNameItemList.add("#{item." + fieldName + "}");
|
||||||
|
}
|
||||||
|
|
||||||
|
String batchInsertXml = "<insert id=\"batchInsert\">\n"
|
||||||
|
+ "INSERT INTO " + tableName + " ("
|
||||||
|
+ String.join(",", fieldNameUnderlineList)
|
||||||
|
+ ") VALUES\n"
|
||||||
|
+ "<foreach collection=\"list\" item=\"item\" separator=\",\">\n"
|
||||||
|
+ "(\n"
|
||||||
|
+ String.join(",\n", fieldNameItemList)
|
||||||
|
+ ")\n"
|
||||||
|
+ "</foreach>\n"
|
||||||
|
+ "</insert>\n";
|
||||||
|
System.err.println(batchInsertXml);
|
||||||
|
|
||||||
|
StringBuilder ifStringBuilder = new StringBuilder();
|
||||||
|
for (int i = 0; i < fieldNameList.size(); i++) {
|
||||||
|
ifStringBuilder.append("<if test=\"item.")
|
||||||
|
.append(fieldNameList.get(i))
|
||||||
|
.append(" != null\">")
|
||||||
|
.append(fieldNameUnderlineList.get(i))
|
||||||
|
.append(" = #{item.")
|
||||||
|
.append(fieldNameList.get(i))
|
||||||
|
.append("},</if>\n");
|
||||||
|
}
|
||||||
|
String batchUpdateXml = "<update id=\"batchUpdateById\">\n"
|
||||||
|
+ "<foreach collection=\"list\" item=\"item\" separator=\";\">\n"
|
||||||
|
+ "UPDATE " + tableName + "\n"
|
||||||
|
+ "<set>\n"
|
||||||
|
+ ifStringBuilder
|
||||||
|
+ "</set>\n"
|
||||||
|
+ "WHERE " + StrUtil.toUnderlineCase(primaryKeyName) + " = #{item." + primaryKeyName + "}\n"
|
||||||
|
+ "</foreach>\n"
|
||||||
|
+ "</update>\n";
|
||||||
|
System.err.println(batchUpdateXml);
|
||||||
|
|
||||||
|
String batchDeleteXml = "<delete id=\"batchDeleteByIds\">\n"
|
||||||
|
+ "delete from " + tableName + " where " + StrUtil.toUnderlineCase(primaryKeyName) + " in\n"
|
||||||
|
+ "<foreach collection=\"list\" item=\"id\" open=\"(\" close=\")\" separator=\",\">\n"
|
||||||
|
+ "#{id}\n"
|
||||||
|
+ "</foreach>\n"
|
||||||
|
+ "</delete>";
|
||||||
|
System.err.println(batchDeleteXml);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
new MybatisMapperBatchOpRender().render(SystemDeptTb.class, "id");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,11 +1,13 @@
|
|||||||
package cn.odboy;
|
package cn.odboy;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.odboy.framework.exception.BadRequestException;
|
||||||
import cn.odboy.system.dal.dataobject.SystemDeptTb;
|
import cn.odboy.system.dal.dataobject.SystemDeptTb;
|
||||||
import cn.odboy.util.KitClassUtil;
|
import cn.odboy.util.KitClassUtil;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -14,38 +16,103 @@ import java.util.stream.Collectors;
|
|||||||
* @author odboy
|
* @author odboy
|
||||||
*/
|
*/
|
||||||
public class MybatisMapperBatchOpRender {
|
public class MybatisMapperBatchOpRender {
|
||||||
/**
|
|
||||||
* 持久类名
|
|
||||||
*/
|
|
||||||
private String entityClassName;
|
|
||||||
/**
|
|
||||||
* 持久类主键类型名
|
|
||||||
*/
|
|
||||||
private String entityPkTypeName;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 渲染MapperXml
|
* 渲染MapperXml
|
||||||
*
|
*
|
||||||
* @param entityClass 持久类
|
* @param entityClass 持久类
|
||||||
* @param keyMapper 哪个是主键
|
* @param primaryKeyName 主键名称
|
||||||
*/
|
*/
|
||||||
public <T, K> void render(Class<?> entityClass, Function<? super T, ? extends K> keyMapper) {
|
public <T, K> void render(Class<?> entityClass, String primaryKeyName) {
|
||||||
String mapperBatchInsert = "void batchInsert(@Param(\"list\") List<$EntityClassName> list);";
|
if (entityClass == null) {
|
||||||
System.err.println(mapperBatchInsert.replace("$EntityClassName", this.entityClassName));
|
throw new BadRequestException("参数 entityClass 必填");
|
||||||
String mapperBatchUpdate = "void batchUpdateById(@Param(\"list\") List<$EntityClassName> list);";
|
}
|
||||||
System.err.println(mapperBatchUpdate.replace("$EntityClassName", this.entityClassName));
|
TableName tableNameAnnotation = entityClass.getAnnotation(TableName.class);
|
||||||
String mapperBatchDelete = "void batchDeleteByIds(@Param(\"list\") List<$EntityPkTypeName> list);";
|
if (tableNameAnnotation == null) {
|
||||||
System.err.println(mapperBatchDelete.replace("$EntityPkTypeName", this.entityPkTypeName));
|
throw new BadRequestException("参数 entityClass 不是一个有效的Mybatis表对象");
|
||||||
|
|
||||||
List<Field> fields = new ArrayList<>();
|
|
||||||
KitClassUtil.getAllFields(entityClass, fields);
|
|
||||||
|
|
||||||
fields = fields.stream().filter(f -> !"serialVersionUID".equals(f.getName())).collect(Collectors.toList());
|
|
||||||
|
|
||||||
System.err.println(fields);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
List<Field> fields = new ArrayList<>();
|
||||||
new MybatisMapperBatchOpRender().render(SystemDeptTb.class, SystemDeptTb::getId);
|
KitClassUtil.getAllFields(entityClass, fields);
|
||||||
|
fields = fields.stream().filter(f -> !"serialVersionUID".equals(f.getName())).collect(Collectors.toList());
|
||||||
|
|
||||||
|
Field primaryKeyField = fields.stream().filter(f -> f.getName().equals(primaryKeyName)).findFirst().orElse(null);
|
||||||
|
if (primaryKeyField == null) {
|
||||||
|
throw new BadRequestException("参数 primaryKeyName 设置有误");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fields = fields.stream().filter(f -> !f.getName().equals(primaryKeyName)).collect(Collectors.toList());
|
||||||
|
|
||||||
|
// 持久类主键类型名
|
||||||
|
String entityPkTypeName = primaryKeyField.getType().getSimpleName();
|
||||||
|
// 持久类名
|
||||||
|
String entityClassName = entityClass.getSimpleName();
|
||||||
|
// 数据表名
|
||||||
|
String tableName = tableNameAnnotation.value();
|
||||||
|
|
||||||
|
System.err.println("============== 渲染Mapper ==================");
|
||||||
|
String mapperBatchInsert = "void batchInsert(@Param(\"list\") List<$EntityClassName> list);";
|
||||||
|
System.err.println(mapperBatchInsert.replace("$EntityClassName", entityClassName));
|
||||||
|
String mapperBatchUpdate = "void batchUpdateById(@Param(\"list\") List<$EntityClassName> list);";
|
||||||
|
System.err.println(mapperBatchUpdate.replace("$EntityClassName", entityClassName));
|
||||||
|
String mapperBatchDelete = "void batchDeleteByIds(@Param(\"list\") List<$EntityPkTypeName> list);";
|
||||||
|
System.err.println(mapperBatchDelete.replace("$EntityPkTypeName", entityPkTypeName));
|
||||||
|
System.err.println("\n============== 渲染MapperXml ==================");
|
||||||
|
List<String> fieldNameList = new ArrayList<>();
|
||||||
|
List<String> fieldNameUnderlineList = new ArrayList<>();
|
||||||
|
List<String> fieldNameItemList = new ArrayList<>();
|
||||||
|
|
||||||
|
for (Field field : fields) {
|
||||||
|
fieldNameList.add(field.getName());
|
||||||
|
}
|
||||||
|
for (String fieldName : fieldNameList) {
|
||||||
|
fieldNameUnderlineList.add(StrUtil.toUnderlineCase(fieldName));
|
||||||
|
fieldNameItemList.add("#{item." + fieldName + "}");
|
||||||
|
}
|
||||||
|
|
||||||
|
String batchInsertXml = "<insert id=\"batchInsert\">\n"
|
||||||
|
+ "INSERT INTO " + tableName + " ("
|
||||||
|
+ String.join(",", fieldNameUnderlineList)
|
||||||
|
+ ") VALUES\n"
|
||||||
|
+ "<foreach collection=\"list\" item=\"item\" separator=\",\">\n"
|
||||||
|
+ "(\n"
|
||||||
|
+ String.join(",\n", fieldNameItemList)
|
||||||
|
+ ")\n"
|
||||||
|
+ "</foreach>\n"
|
||||||
|
+ "</insert>\n";
|
||||||
|
System.err.println(batchInsertXml);
|
||||||
|
|
||||||
|
StringBuilder ifStringBuilder = new StringBuilder();
|
||||||
|
for (int i = 0; i < fieldNameList.size(); i++) {
|
||||||
|
ifStringBuilder.append("<if test=\"item.")
|
||||||
|
.append(fieldNameList.get(i))
|
||||||
|
.append(" != null\">")
|
||||||
|
.append(fieldNameUnderlineList.get(i))
|
||||||
|
.append(" = #{item.")
|
||||||
|
.append(fieldNameList.get(i))
|
||||||
|
.append("},</if>\n");
|
||||||
|
}
|
||||||
|
String batchUpdateXml = "<update id=\"batchUpdateById\">\n"
|
||||||
|
+ "<foreach collection=\"list\" item=\"item\" separator=\";\">\n"
|
||||||
|
+ "UPDATE " + tableName + "\n"
|
||||||
|
+ "<set>\n"
|
||||||
|
+ ifStringBuilder
|
||||||
|
+ "</set>\n"
|
||||||
|
+ "WHERE " + StrUtil.toUnderlineCase(primaryKeyName) + " = #{item." + primaryKeyName + "}\n"
|
||||||
|
+ "</foreach>\n"
|
||||||
|
+ "</update>\n";
|
||||||
|
System.err.println(batchUpdateXml);
|
||||||
|
|
||||||
|
String batchDeleteXml = "<delete id=\"batchDeleteByIds\">\n"
|
||||||
|
+ "delete from " + tableName + " where " + StrUtil.toUnderlineCase(primaryKeyName) + " in\n"
|
||||||
|
+ "<foreach collection=\"list\" item=\"id\" open=\"(\" close=\")\" separator=\",\">\n"
|
||||||
|
+ "#{id}\n"
|
||||||
|
+ "</foreach>\n"
|
||||||
|
+ "</delete>";
|
||||||
|
System.err.println(batchDeleteXml);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
new MybatisMapperBatchOpRender().render(SystemDeptTb.class, "id");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user