From f6b040a4ff0837a0aa64bc27b11713d2b4a3fb21 Mon Sep 17 00:00:00 2001 From: hewei Date: Thu, 17 May 2018 13:28:15 +0800 Subject: [PATCH] =?UTF-8?q?BatchInsertPlugin=20=E5=A2=9E=E5=8A=A0=20allowM?= =?UTF-8?q?ultiQueries=E9=85=8D=E7=BD=AE=EF=BC=8C=E5=BC=80=E5=90=AF?= =?UTF-8?q?=E6=97=B6=E5=9C=A8=E4=B8=8D=E4=BC=A0=E6=8C=87=E5=AE=9A=E5=88=97?= =?UTF-8?q?=E6=97=B6=E5=90=AF=E7=94=A8=E5=8E=9F=E7=94=9F=E9=9D=9E=E7=A9=BA?= =?UTF-8?q?=E5=88=A4=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../generator/plugins/BatchInsertPlugin.java | 104 ++++++++++++++---- .../plugins/BatchInsertPluginTest.java | 56 ++++++++++ ...batis-generator-with-allowMultiQueries.xml | 64 +++++++++++ 3 files changed, 202 insertions(+), 22 deletions(-) create mode 100644 src/test/resources/scripts/BatchInsertPlugin/mybatis-generator-with-allowMultiQueries.xml diff --git a/src/main/java/com/itfsw/mybatis/generator/plugins/BatchInsertPlugin.java b/src/main/java/com/itfsw/mybatis/generator/plugins/BatchInsertPlugin.java index 4a0d74d..7a68d93 100644 --- a/src/main/java/com/itfsw/mybatis/generator/plugins/BatchInsertPlugin.java +++ b/src/main/java/com/itfsw/mybatis/generator/plugins/BatchInsertPlugin.java @@ -23,8 +23,11 @@ import org.mybatis.generator.api.dom.java.*; import org.mybatis.generator.api.dom.xml.*; import org.mybatis.generator.codegen.mybatis3.ListUtilities; import org.mybatis.generator.codegen.mybatis3.MyBatis3FormattingUtilities; +import org.mybatis.generator.internal.util.StringUtility; +import java.util.ArrayList; import java.util.List; +import java.util.Properties; /** * --------------------------------------------------------------------------- @@ -37,6 +40,8 @@ import java.util.List; public class BatchInsertPlugin extends BasePlugin { public static final String METHOD_BATCH_INSERT = "batchInsert"; // 方法名 public static final String METHOD_BATCH_INSERT_SELECTIVE = "batchInsertSelective"; // 方法名 + public static final String PRO_ALLOW_MULTI_QUERIES = "allowMultiQueries"; // property allowMultiQueries + private boolean allowMultiQueries = false; // 是否允许多sql提交 /** * {@inheritDoc} @@ -59,6 +64,15 @@ public class BatchInsertPlugin extends BasePlugin { return false; } + // 插件是否开启了多sql提交 + Properties properties = this.getProperties(); + String allowMultiQueries = properties.getProperty(PRO_ALLOW_MULTI_QUERIES); + this.allowMultiQueries = allowMultiQueries == null ? false : StringUtility.isTrue(allowMultiQueries); + if (this.allowMultiQueries) { + // 提示用户注意信息 + warnings.add("itfsw:插件" + this.getClass().getTypeName() + "插件您开启了allowMultiQueries支持,注意在jdbc url 配置中增加“allowMultiQueries=true”支持(不怎么建议使用该功能,开启多sql提交会增加sql注入的风险,请确保你所有sql都使用MyBatis书写,请不要使用statement进行sql提交)!"); + } + return super.validate(warnings); } @@ -143,23 +157,75 @@ public class BatchInsertPlugin extends BasePlugin { // values 构建 batchInsertEle.addElement(new TextElement("values")); batchInsertEle.addElement(foreachElement); - if (context.getPlugins().sqlMapInsertElementGenerated(batchInsertEle, introspectedTable)) { - document.getRootElement().addElement(batchInsertEle); - logger.debug("itfsw(批量插入插件):" + introspectedTable.getMyBatis3XmlMapperFileName() + "增加batchInsert实现方法。"); - } + document.getRootElement().addElement(batchInsertEle); + logger.debug("itfsw(批量插入插件):" + introspectedTable.getMyBatis3XmlMapperFileName() + "增加batchInsert实现方法。"); // 2. batchInsertSelective - XmlElement element = new XmlElement("insert"); - element.addAttribute(new Attribute("id", METHOD_BATCH_INSERT_SELECTIVE)); - // 参数类型 - element.addAttribute(new Attribute("parameterType", "map")); + XmlElement batchInsertSelectiveEle = new XmlElement("insert"); // 添加注释(!!!必须添加注释,overwrite覆盖生成时,@see XmlFileMergerJaxp.isGeneratedNode会去判断注释中是否存在OLD_ELEMENT_TAGS中的一点,例子:@mbg.generated) - commentGenerator.addComment(element); + commentGenerator.addComment(batchInsertSelectiveEle); + + batchInsertSelectiveEle.addAttribute(new Attribute("id", METHOD_BATCH_INSERT_SELECTIVE)); + // 参数类型 + batchInsertSelectiveEle.addAttribute(new Attribute("parameterType", "map")); // 使用JDBC的getGenereatedKeys方法获取主键并赋值到keyProperty设置的领域模型属性中。所以只支持MYSQL和SQLServer - XmlElementGeneratorTools.useGeneratedKeys(element, introspectedTable); + XmlElementGeneratorTools.useGeneratedKeys(batchInsertSelectiveEle, introspectedTable); - element.addElement(new TextElement("insert into " + introspectedTable.getFullyQualifiedTableNameAtRuntime() + " (")); + // 支持原生字段非空判断 + if (this.allowMultiQueries) { + XmlElement chooseEle = new XmlElement("choose"); + + // selective 增强 + XmlElement selectiveEnhancedEle = new XmlElement("when"); + selectiveEnhancedEle.addAttribute(new Attribute("test", "selective != null and selective.length > 0")); + chooseEle.addElement(selectiveEnhancedEle); + + selectiveEnhancedEle.getElements().addAll(this.generateSelectiveEnhancedEles(introspectedTable)); + + // 原生非空判断语句 + XmlElement selectiveNormalEle = new XmlElement("otherwise"); + chooseEle.addElement(selectiveNormalEle); + + XmlElement foreachEle = new XmlElement("foreach"); + selectiveNormalEle.addElement(foreachEle); + foreachEle.addAttribute(new Attribute("collection", "list")); + foreachEle.addAttribute(new Attribute("item", "item")); + foreachEle.addAttribute(new Attribute("separator", ";")); + + + foreachEle.addElement(new TextElement("insert into " + introspectedTable.getFullyQualifiedTableNameAtRuntime())); + + XmlElement insertTrimElement = new XmlElement("trim"); + foreachEle.addElement(insertTrimElement); + insertTrimElement.addElement(XmlElementGeneratorTools.generateKeysSelective(ListUtilities.removeIdentityAndGeneratedAlwaysColumns(introspectedTable.getAllColumns()), "item.")); + + foreachEle.addElement(new TextElement("values")); + + XmlElement valuesTrimElement = new XmlElement("trim"); + foreachEle.addElement(valuesTrimElement); + valuesTrimElement.addElement(XmlElementGeneratorTools.generateValuesSelective(ListUtilities.removeIdentityAndGeneratedAlwaysColumns(introspectedTable.getAllColumns()), "item.")); + + batchInsertSelectiveEle.addElement(chooseEle); + } else { + batchInsertSelectiveEle.getElements().addAll(this.generateSelectiveEnhancedEles(introspectedTable)); + } + + document.getRootElement().addElement(batchInsertSelectiveEle); + logger.debug("itfsw(批量插入插件):" + introspectedTable.getMyBatis3XmlMapperFileName() + "增加batchInsertSelective实现方法。"); + + return true; + } + + /** + * 生成insert selective 增强的插入语句 + * @param introspectedTable + * @return + */ + private List generateSelectiveEnhancedEles(IntrospectedTable introspectedTable) { + List eles = new ArrayList<>(); + + eles.add(new TextElement("insert into " + introspectedTable.getFullyQualifiedTableNameAtRuntime() + " (")); XmlElement foreachInsertColumns = new XmlElement("foreach"); foreachInsertColumns.addAttribute(new Attribute("collection", "selective")); @@ -167,12 +233,12 @@ public class BatchInsertPlugin extends BasePlugin { foreachInsertColumns.addAttribute(new Attribute("separator", ",")); foreachInsertColumns.addElement(new TextElement("${column.value}")); - element.addElement(foreachInsertColumns); + eles.add(foreachInsertColumns); - element.addElement(new TextElement(")")); + eles.add(new TextElement(")")); // values - element.addElement(new TextElement("values")); + eles.add(new TextElement("values")); // foreach values XmlElement foreachValues = new XmlElement("foreach"); @@ -203,14 +269,8 @@ public class BatchInsertPlugin extends BasePlugin { foreachValues.addElement(new TextElement(")")); - element.addElement(foreachValues); + eles.add(foreachValues); - if (context.getPlugins().sqlMapInsertElementGenerated(element, introspectedTable)) { - document.getRootElement().addElement(element); - logger.debug("itfsw(批量插入插件):" + introspectedTable.getMyBatis3XmlMapperFileName() + "增加batchInsertSelective实现方法。"); - } - - return true; + return eles; } - } \ No newline at end of file diff --git a/src/test/java/com/itfsw/mybatis/generator/plugins/BatchInsertPluginTest.java b/src/test/java/com/itfsw/mybatis/generator/plugins/BatchInsertPluginTest.java index 6d8037c..ea5e0aa 100644 --- a/src/test/java/com/itfsw/mybatis/generator/plugins/BatchInsertPluginTest.java +++ b/src/test/java/com/itfsw/mybatis/generator/plugins/BatchInsertPluginTest.java @@ -66,6 +66,11 @@ public class BatchInsertPluginTest { Assert.assertTrue(tool.getWarnings().size() == 2); Assert.assertEquals(tool.getWarnings().get(0), "itfsw:插件com.itfsw.mybatis.generator.plugins.BatchInsertPlugin插件需配合com.itfsw.mybatis.generator.plugins.ModelColumnPlugin插件使用!"); + + // 2. 普通提示 + tool = MyBatisGeneratorTool.create("scripts/BatchInsertPlugin/mybatis-generator-with-allowMultiQueries.xml"); + tool.generate(); + Assert.assertEquals(tool.getWarnings().get(0), "itfsw:插件com.itfsw.mybatis.generator.plugins.BatchInsertPlugin插件您开启了allowMultiQueries支持,注意在jdbc url 配置中增加“allowMultiQueries=true”支持(不怎么建议使用该功能,开启多sql提交会增加sql注入的风险,请确保你所有sql都使用MyBatis书写,请不要使用statement进行sql提交)!"); } /** @@ -164,6 +169,11 @@ public class BatchInsertPluginTest { // 2. 执行sql Object count = tbMapper.invoke("batchInsert", params); Assert.assertEquals(count, 2); + + for (int i = 0; i < params.size(); i++) { + ObjectUtil item = new ObjectUtil(params.get(i)); + Assert.assertEquals(item.get("id"), 1L + i); + } } }); } @@ -204,4 +214,50 @@ public class BatchInsertPluginTest { } }); } + + /** + * 测试开启 AllowMultiQueries 支持 + */ + @Test + public void testAllowMultiQueries() throws Exception { + MyBatisGeneratorTool tool = MyBatisGeneratorTool.create("scripts/BatchInsertPlugin/mybatis-generator-with-allowMultiQueries.xml"); + + // 1. 测试增强的selective + tool.generate(() -> DBHelper.resetDB("scripts/BatchInsertPlugin/init.sql"), new AbstractShellCallback() { + @Override + public void reloadProject(SqlSession sqlSession, ClassLoader loader, String packagz) throws Exception { + ObjectUtil tbMapper = new ObjectUtil(sqlSession.getMapper(loader.loadClass(packagz + ".TbMapper"))); + List params = new ArrayList<>(); + params.add(new ObjectUtil(loader, packagz + ".Tb").set("field1", "test").getObject()); + params.add(new ObjectUtil(loader, packagz + ".Tb").set("field1", "test").set("field2", 1).getObject()); + + ObjectUtil columnField2 = new ObjectUtil(loader, packagz + ".Tb$Column#field2"); + Object columns = Array.newInstance(columnField2.getCls(), 1); + Array.set(columns, 0, columnField2.getObject()); + + String sql = SqlHelper.getFormatMapperSql(tbMapper.getObject(), "batchInsertSelective", params, columns); + Assert.assertEquals(sql, "insert into tb ( field2 ) values ( null ) , ( 1 )"); + // 2. 执行sql + Object count = tbMapper.invoke("batchInsertSelective", params, columns); + Assert.assertEquals(count, 2); + } + }); + + // 2. 测试原生非空判断 + tool.generate(() -> DBHelper.resetDB("scripts/BatchInsertPlugin/init.sql"), new AbstractShellCallback() { + @Override + public void reloadProject(SqlSession sqlSession, ClassLoader loader, String packagz) throws Exception { + ObjectUtil tbMapper = new ObjectUtil(sqlSession.getMapper(loader.loadClass(packagz + ".TbMapper"))); + List params = new ArrayList<>(); + params.add(new ObjectUtil(loader, packagz + ".Tb").set("field1", "test").getObject()); + params.add(new ObjectUtil(loader, packagz + ".Tb").set("field1", "test").set("field2", 1).getObject()); + + String sql = SqlHelper.getFormatMapperSql(tbMapper.getObject(), "batchInsertSelective", params, null); + Assert.assertEquals(sql, "insert into tb ( field1 ) values ( 'test' ) ; insert into tb ( field1, field2 ) values ( 'test', 1 )"); + // 2. 执行sql + Object count = tbMapper.invoke("batchInsertSelective", params, null); + Assert.assertTrue((int) count > 0); + } + }); + } } diff --git a/src/test/resources/scripts/BatchInsertPlugin/mybatis-generator-with-allowMultiQueries.xml b/src/test/resources/scripts/BatchInsertPlugin/mybatis-generator-with-allowMultiQueries.xml new file mode 100644 index 0000000..6338d35 --- /dev/null +++ b/src/test/resources/scripts/BatchInsertPlugin/mybatis-generator-with-allowMultiQueries.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+
+
\ No newline at end of file