批量插入

This commit is contained in:
iqudoo
2026-04-12 19:07:12 +08:00
parent abfab32498
commit dc7ccf905f
3 changed files with 9 additions and 180 deletions

View File

@@ -42,6 +42,7 @@
- `countByTrash({Example} example)` - 统计回收站记录数 - `countByTrash({Example} example)` - 统计回收站记录数
- `countByTrashWithPage({Example} example)` - 统计分页回收站记录数 - `countByTrashWithPage({Example} example)` - 统计分页回收站记录数
- `insert({Model} record)` - 插入记录(自动生成 GUID、设置默认值 - `insert({Model} record)` - 插入记录(自动生成 GUID、设置默认值
- `batchInsert(List<{Model}> records)` - 批量插入记录(自动生成 GUID、设置默认值
- `updateByExampleSelective({Model} record, {Example} example)` - 按条件更新记录 - `updateByExampleSelective({Model} record, {Example} example)` - 按条件更新记录
- `update({Model} record)` - 更新记录(支持乐观锁) - `update({Model} record)` - 更新记录(支持乐观锁)

View File

@@ -249,7 +249,6 @@ public class TapeMybatisGeneratorPlugin extends PluginAdapter {
JavaVisibility.PUBLIC, JavaVisibility.PUBLIC,
stringType stringType
); );
getWhereString.addAnnotation("@SuppressWarnings(\"DuplicatedCode\")");
getWhereString = ElementTools.generateMethodBody( getWhereString = ElementTools.generateMethodBody(
getWhereString, getWhereString,
"if (getOredCriteria() != null) {", "if (getOredCriteria() != null) {",
@@ -342,7 +341,7 @@ public class TapeMybatisGeneratorPlugin extends PluginAdapter {
// ============================================ batchInsert ========================================== // ============================================ batchInsert ==========================================
private void addBatchInsertClientMethod(Interface interfaze, IntrospectedTable introspectedTable) { private void addBatchInsertClientMethod(Interface interfaceObj, IntrospectedTable introspectedTable) {
if (introspectedTable.getAllColumns().isEmpty()) { if (introspectedTable.getAllColumns().isEmpty()) {
return; return;
} }
@@ -360,9 +359,9 @@ public class TapeMybatisGeneratorPlugin extends PluginAdapter {
batchInsert.setReturnType(FullyQualifiedJavaType.getIntInstance()); batchInsert.setReturnType(FullyQualifiedJavaType.getIntInstance());
batchInsert.addParameter(recordsParam); batchInsert.addParameter(recordsParam);
interfaze.addImportedType(new FullyQualifiedJavaType("java.util.List")); interfaceObj.addImportedType(new FullyQualifiedJavaType("java.util.List"));
interfaze.addImportedType(new FullyQualifiedJavaType("org.apache.ibatis.annotations.Param")); interfaceObj.addImportedType(new FullyQualifiedJavaType("org.apache.ibatis.annotations.Param"));
interfaze.addMethod(batchInsert); interfaceObj.addMethod(batchInsert);
} }
private void addBatchInsertXmlElement(Document document, IntrospectedTable introspectedTable) { private void addBatchInsertXmlElement(Document document, IntrospectedTable introspectedTable) {
@@ -400,89 +399,6 @@ public class TapeMybatisGeneratorPlugin extends PluginAdapter {
document.getRootElement().addElement(insert); document.getRootElement().addElement(insert);
} }
// ============================================ batchUpdate ==========================================
private static String actualColumnByJavaProperty(IntrospectedTable introspectedTable, String javaProperty) {
for (IntrospectedColumn column : introspectedTable.getAllColumns()) {
if (javaProperty.equals(column.getJavaProperty())) {
return column.getActualColumnName();
}
}
return null;
}
private void addBatchUpdateClientMethod(Interface interfaze, IntrospectedTable introspectedTable) {
if (introspectedTable.getAllColumns().isEmpty()) {
return;
}
if (actualColumnByJavaProperty(introspectedTable, "guid") == null
|| actualColumnByJavaProperty(introspectedTable, "dataVersion") == null) {
return;
}
FullyQualifiedJavaType rowType = ElementTools.hasBLOBColumns(introspectedTable)
? ElementTools.getModelTypeWithBLOBs(introspectedTable)
: ElementTools.getModelTypeWithoutBLOBs(introspectedTable);
FullyQualifiedJavaType listType = FullyQualifiedJavaType.getNewListInstance();
listType.addTypeArgument(rowType);
Parameter recordsParam = new Parameter(listType, "records");
recordsParam.addAnnotation("@Param(\"records\")");
Method batchUpdate = new Method("batchUpdate");
batchUpdate.setAbstract(true);
batchUpdate.setVisibility(JavaVisibility.PUBLIC);
batchUpdate.setReturnType(FullyQualifiedJavaType.getIntInstance());
batchUpdate.addParameter(recordsParam);
interfaze.addImportedType(new FullyQualifiedJavaType("java.util.List"));
interfaze.addImportedType(new FullyQualifiedJavaType("org.apache.ibatis.annotations.Param"));
interfaze.addMethod(batchUpdate);
}
private void addBatchUpdateXmlElement(Document document, IntrospectedTable introspectedTable) {
if (introspectedTable.getAllColumns().isEmpty()) {
return;
}
String guidCol = actualColumnByJavaProperty(introspectedTable, "guid");
String dataVersionCol = actualColumnByJavaProperty(introspectedTable, "dataVersion");
if (guidCol == null || dataVersionCol == null) {
return;
}
String isDeleteCol = actualColumnByJavaProperty(introspectedTable, "isDelete");
String isHiddenCol = actualColumnByJavaProperty(introspectedTable, "isHidden");
String tableName = introspectedTable.getFullyQualifiedTableNameAtRuntime();
XmlElement setElement = new XmlElement("set");
for (IntrospectedColumn column : introspectedTable.getAllColumns()) {
setElement.addElement(new TextElement(
column.getActualColumnName() + " = #{item." + column.getJavaProperty() + "},"));
}
StringBuilder where = new StringBuilder();
where.append("where ").append(guidCol).append(" = #{item.guid}");
if (isDeleteCol != null) {
where.append(" and ").append(isDeleteCol).append(" = 0");
}
if (isHiddenCol != null) {
where.append(" and ").append(isHiddenCol).append(" = 0");
}
where.append(" and ").append(dataVersionCol).append(" = #{item.dataVersion} - 1");
XmlElement foreach = new XmlElement("foreach");
foreach.addAttribute(new Attribute("collection", "records"));
foreach.addAttribute(new Attribute("item", "item"));
foreach.addAttribute(new Attribute("separator", ";"));
foreach.addElement(new TextElement("update " + tableName));
foreach.addElement(setElement);
foreach.addElement(new TextElement(where.toString()));
XmlElement update = new XmlElement("update");
update.addAttribute(new Attribute("id", "batchUpdate"));
update.addElement(foreach);
document.getRootElement().addElement(update);
}
// ============================================ selectPrimaryKeyByExample ========================================== // ============================================ selectPrimaryKeyByExample ==========================================
@Override @Override
@@ -491,7 +407,6 @@ public class TapeMybatisGeneratorPlugin extends PluginAdapter {
return super.clientGenerated(interfaze, introspectedTable); return super.clientGenerated(interfaze, introspectedTable);
} }
addBatchInsertClientMethod(interfaze, introspectedTable); addBatchInsertClientMethod(interfaze, introspectedTable);
addBatchUpdateClientMethod(interfaze, introspectedTable);
if (introspectedTable.getPrimaryKeyColumns().size() <= 0) { if (introspectedTable.getPrimaryKeyColumns().size() <= 0) {
return super.clientGenerated(interfaze, introspectedTable); return super.clientGenerated(interfaze, introspectedTable);
} }
@@ -521,7 +436,6 @@ public class TapeMybatisGeneratorPlugin extends PluginAdapter {
return super.sqlMapDocumentGenerated(document, introspectedTable); return super.sqlMapDocumentGenerated(document, introspectedTable);
} }
addBatchInsertXmlElement(document, introspectedTable); addBatchInsertXmlElement(document, introspectedTable);
addBatchUpdateXmlElement(document, introspectedTable);
if (introspectedTable.getPrimaryKeyColumns().size() <= 0) { if (introspectedTable.getPrimaryKeyColumns().size() <= 0) {
return super.sqlMapDocumentGenerated(document, introspectedTable); return super.sqlMapDocumentGenerated(document, introspectedTable);
} }

View File

@@ -99,10 +99,9 @@ public class TapeRepositoryGeneratorPlugin extends PluginAdapter {
String repositoryInterfaceName = "I" + domainObjectName + "Repository"; String repositoryInterfaceName = "I" + domainObjectName + "Repository";
String repositoryImplName = domainObjectName + "RepositoryImpl"; String repositoryImplName = domainObjectName + "RepositoryImpl";
boolean hasBLOBColumns = ElementTools.hasBLOBColumns(introspectedTable); boolean hasBLOBColumns = ElementTools.hasBLOBColumns(introspectedTable);
boolean supportsBatchUpdate = supportsTapeBatchUpdate(introspectedTable);
// 生成Repository接口核心修改手动添加所有方法不再继承父接口 // 生成Repository接口核心修改手动添加所有方法不再继承父接口
Interface repositoryInterface = generateRepositoryInterface(repositoryInterfaceName, domainObjectName, exampleClassName, supportsBatchUpdate); Interface repositoryInterface = generateRepositoryInterface(repositoryInterfaceName, domainObjectName, exampleClassName);
GeneratedJavaFile interfaceFile = new GeneratedJavaFile( GeneratedJavaFile interfaceFile = new GeneratedJavaFile(
repositoryInterface, repositoryInterface,
targetProject, targetProject,
@@ -119,8 +118,7 @@ public class TapeRepositoryGeneratorPlugin extends PluginAdapter {
exampleClassName, exampleClassName,
mapperClassName, mapperClassName,
introspectedTable, introspectedTable,
hasBLOBColumns, hasBLOBColumns
supportsBatchUpdate
); );
GeneratedJavaFile implFile = new GeneratedJavaFile( GeneratedJavaFile implFile = new GeneratedJavaFile(
repositoryImpl, repositoryImpl,
@@ -137,26 +135,6 @@ public class TapeRepositoryGeneratorPlugin extends PluginAdapter {
return generatedJavaFiles; return generatedJavaFiles;
} }
/**
* 判断是否为视图表(支持多关键字匹配)
*/
/**
* 与 {@link TapeMybatisGeneratorPlugin} 中 batchUpdate 生成条件一致:需存在 guid、dataVersion 列。
*/
private static boolean supportsTapeBatchUpdate(IntrospectedTable introspectedTable) {
boolean hasGuid = false;
boolean hasDataVersion = false;
for (IntrospectedColumn column : introspectedTable.getAllColumns()) {
if ("guid".equals(column.getJavaProperty())) {
hasGuid = true;
}
if ("dataVersion".equals(column.getJavaProperty())) {
hasDataVersion = true;
}
}
return hasGuid && hasDataVersion;
}
private boolean isViewTable(String tableName) { private boolean isViewTable(String tableName) {
if (StringUtility.stringHasValue(viewKeyWords)) { if (StringUtility.stringHasValue(viewKeyWords)) {
String[] keywords = viewKeyWords.split(","); String[] keywords = viewKeyWords.split(",");
@@ -172,7 +150,7 @@ public class TapeRepositoryGeneratorPlugin extends PluginAdapter {
/** /**
* 核心修改生成Repository接口手动添加所有方法无继承匹配指定格式 * 核心修改生成Repository接口手动添加所有方法无继承匹配指定格式
*/ */
private Interface generateRepositoryInterface(String interfaceName, String modelClassName, String exampleClassName, boolean supportsBatchUpdate) { private Interface generateRepositoryInterface(String interfaceName, String modelClassName, String exampleClassName) {
Interface repositoryInterface = new Interface(facadeRepositoryPackage + "." + interfaceName); Interface repositoryInterface = new Interface(facadeRepositoryPackage + "." + interfaceName);
repositoryInterface.setVisibility(JavaVisibility.PUBLIC); repositoryInterface.setVisibility(JavaVisibility.PUBLIC);
@@ -363,17 +341,6 @@ public class TapeRepositoryGeneratorPlugin extends PluginAdapter {
updateMethod.setAbstract(true); updateMethod.setAbstract(true);
repositoryInterface.addMethod(updateMethod); repositoryInterface.addMethod(updateMethod);
// 20b. batchUpdate与 Mapper 一致,仅 guid + dataVersion 齐备时生成)
if (supportsBatchUpdate) {
Method batchUpdateMethod = new Method("batchUpdate");
batchUpdateMethod.setVisibility(JavaVisibility.PUBLIC);
batchUpdateMethod.setReturnType(new FullyQualifiedJavaType("int"));
batchUpdateMethod.addParameter(new Parameter(new FullyQualifiedJavaType("List<" + modelClassName + ">"), "records"));
batchUpdateMethod.addException(new FullyQualifiedJavaType("Throwable"));
batchUpdateMethod.setAbstract(true);
repositoryInterface.addMethod(batchUpdateMethod);
}
// 21. updateByExampleSelective // 21. updateByExampleSelective
Method updateByExampleSelectiveMethod = new Method("updateByExampleSelective"); Method updateByExampleSelectiveMethod = new Method("updateByExampleSelective");
updateByExampleSelectiveMethod.setVisibility(JavaVisibility.PUBLIC); updateByExampleSelectiveMethod.setVisibility(JavaVisibility.PUBLIC);
@@ -397,8 +364,7 @@ public class TapeRepositoryGeneratorPlugin extends PluginAdapter {
String exampleClassName, String exampleClassName,
String mapperClassName, String mapperClassName,
IntrospectedTable introspectedTable, IntrospectedTable introspectedTable,
boolean hasBLOBColumns, boolean hasBLOBColumns) {
boolean supportsBatchUpdate) {
TopLevelClass implClass = new TopLevelClass(domainRepositoryPackage + "." + implClassName); TopLevelClass implClass = new TopLevelClass(domainRepositoryPackage + "." + implClassName);
implClass.setVisibility(JavaVisibility.PUBLIC); implClass.setVisibility(JavaVisibility.PUBLIC);
@@ -431,9 +397,6 @@ public class TapeRepositoryGeneratorPlugin extends PluginAdapter {
generateInsertMethod(implClass, modelClassName, mapperFieldName, introspectedTable); generateInsertMethod(implClass, modelClassName, mapperFieldName, introspectedTable);
generateBatchInsertMethod(implClass, modelClassName, mapperFieldName, introspectedTable); generateBatchInsertMethod(implClass, modelClassName, mapperFieldName, introspectedTable);
generateUpdateMethod(implClass, modelClassName, exampleClassName, mapperFieldName, introspectedTable, hasBLOBColumns); generateUpdateMethod(implClass, modelClassName, exampleClassName, mapperFieldName, introspectedTable, hasBLOBColumns);
if (supportsBatchUpdate) {
generateBatchUpdateMethod(implClass, modelClassName, mapperFieldName, introspectedTable);
}
generateUpdateByExampleSelectiveMethod(implClass, modelClassName, exampleClassName, mapperFieldName); generateUpdateByExampleSelectiveMethod(implClass, modelClassName, exampleClassName, mapperFieldName);
generateDeleteByIdMethod(implClass, modelClassName, mapperFieldName); generateDeleteByIdMethod(implClass, modelClassName, mapperFieldName);
generateDeleteAllMethod(implClass, modelClassName, exampleClassName, mapperFieldName); generateDeleteAllMethod(implClass, modelClassName, exampleClassName, mapperFieldName);
@@ -779,55 +742,6 @@ public class TapeRepositoryGeneratorPlugin extends PluginAdapter {
implClass.addMethod(method); implClass.addMethod(method);
} }
private void generateBatchUpdateMethod(TopLevelClass implClass, String modelClassName, String mapperFieldName, IntrospectedTable introspectedTable) {
Method method = new Method("batchUpdate");
method.addAnnotation("@Override");
method.setVisibility(JavaVisibility.PUBLIC);
method.setReturnType(new FullyQualifiedJavaType("int"));
method.addParameter(new Parameter(new FullyQualifiedJavaType("List<" + modelClassName + ">"), "records"));
method.addException(new FullyQualifiedJavaType("Throwable"));
method.addBodyLine("if (records == null || records.isEmpty()) {");
method.addBodyLine("return 0;");
method.addBodyLine("}");
method.addBodyLine("List<" + modelClassName + "> batch = new ArrayList<>();");
method.addBodyLine("for (" + modelClassName + " record : records) {");
method.addBodyLine(modelClassName + " aDo = findValidById(record.getGuid());");
method.addBodyLine("if (aDo == null) {");
method.addBodyLine("throw new Throwable(\"Database record not found, " + modelClassName + " GUID:\" + record.getGuid());");
method.addBodyLine("}");
for (IntrospectedColumn column : introspectedTable.getAllColumns()) {
String fieldName = column.getJavaProperty();
String setterMethod = "set" + upperFirst(fieldName);
String getterMethod = "get" + upperFirst(fieldName);
if ("guid".equals(fieldName) || "isDelete".equals(fieldName) || "isHidden".equals(fieldName)
|| "deleteToken".equals(fieldName) || "dataVersion".equals(fieldName)
|| "createTime".equals(fieldName) || "updateTime".equals(fieldName)) {
continue;
}
method.addBodyLine("if (record." + getterMethod + "() != null) {");
method.addBodyLine("aDo." + setterMethod + "(record." + getterMethod + "());");
method.addBodyLine("}");
}
method.addBodyLine("aDo.setDataVersion(aDo.getDataVersion() + 1);");
method.addBodyLine("aDo.setUpdateTime(new Date());");
method.addBodyLine("record.setDataVersion(aDo.getDataVersion());");
method.addBodyLine("record.setUpdateTime(aDo.getUpdateTime());");
method.addBodyLine("batch.add(aDo);");
method.addBodyLine("}");
method.addBodyLine("int count = " + mapperFieldName + ".batchUpdate(batch);");
method.addBodyLine("if (count == batch.size()) {");
method.addBodyLine("return count;");
method.addBodyLine("}");
method.addBodyLine("throw new Throwable(\"Database batchUpdate failed, " + modelClassName + " affected: \" + count + \", expected: \" + batch.size());");
implClass.addMethod(method);
}
private void generateUpdateByExampleSelectiveMethod(TopLevelClass implClass, String modelClassName, String exampleClassName, String mapperFieldName) { private void generateUpdateByExampleSelectiveMethod(TopLevelClass implClass, String modelClassName, String exampleClassName, String mapperFieldName) {
Method method = new Method("updateByExampleSelective"); Method method = new Method("updateByExampleSelective");
method.addAnnotation("@Override"); method.addAnnotation("@Override");