diff --git a/src/main/java/com/itfsw/mybatis/generator/plugins/UpsertPlugin.java b/src/main/java/com/itfsw/mybatis/generator/plugins/UpsertPlugin.java index 420a439..d31ba0e 100644 --- a/src/main/java/com/itfsw/mybatis/generator/plugins/UpsertPlugin.java +++ b/src/main/java/com/itfsw/mybatis/generator/plugins/UpsertPlugin.java @@ -23,9 +23,11 @@ import org.mybatis.generator.api.IntrospectedTable; 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.Arrays; +import java.util.Iterator; import java.util.List; import java.util.Properties; @@ -42,13 +44,19 @@ public class UpsertPlugin extends BasePlugin { public static final String METHOD_UPSERT_WITH_BLOBS = "upsertWithBLOBs"; // 方法名 public static final String METHOD_UPSERT_SELECTIVE = "upsertSelective"; // 方法名 + public static final String METHOD_BATCH_UPSERT = "batchUpsert"; // 方法名 + public static final String METHOD_BATCH_UPSERT_WITH_BLOBS = "batchUpsertWithBLOBs"; // 方法名 + public static final String METHOD_BATCH_UPSERT_SELECTIVE = "batchUpsertSelective"; // 方法名 + public static final String METHOD_UPSERT_BY_EXAMPLE = "upsertByExample"; // 方法名 public static final String METHOD_UPSERT_BY_EXAMPLE_WITH_BLOBS = "upsertByExampleWithBLOBs"; // 方法名 public static final String METHOD_UPSERT_BY_EXAMPLE_SELECTIVE = "upsertByExampleSelective"; // 方法名 public static final String PRO_ALLOW_MULTI_QUERIES = "allowMultiQueries"; // property allowMultiQueries + public static final String PRO_ALLOW_BATCH_UPSERT = "allowBatchUpsert"; // property allowBatch private boolean allowMultiQueries = false; // 是否允许多sql提交 + private boolean allowBatchUpsert = false; /** * {@inheritDoc} @@ -71,6 +79,16 @@ public class UpsertPlugin extends BasePlugin { warnings.add("itfsw:插件" + this.getClass().getTypeName() + "插件您开启了allowMultiQueries支持,注意在jdbc url 配置中增加“allowMultiQueries=true”支持(不怎么建议使用该功能,开启多sql提交会增加sql注入的风险,请确保你所有sql都使用MyBatis书写,请不要使用statement进行sql提交)!"); } + // 是否允许批量 + String allowBatchUpsert = properties.getProperty(PRO_ALLOW_BATCH_UPSERT); + this.allowBatchUpsert = allowBatchUpsert == null ? false : StringUtility.isTrue(allowBatchUpsert); + + // 批量时依赖插件 ModelColumnPlugin + if (this.allowBatchUpsert && !PluginTools.checkDependencyPlugin(context, ModelColumnPlugin.class)) { + // 提示用户注意信息 + warnings.add("itfsw:插件" + this.getClass().getTypeName() + "插件您开启了allowBatchUpsert支持,请配置依赖的插件" + ModelColumnPlugin.class.getTypeName() + "!"); + } + return super.validate(warnings); } @@ -108,7 +126,7 @@ public class UpsertPlugin extends BasePlugin { commentGenerator.addGeneralMethodComment(mUpsertWithBLOBs, introspectedTable); // interface 增加方法 FormatTools.addMethodWithBestPosition(interfaze, mUpsertWithBLOBs); - logger.debug("itfsw(存在即更新插件):" + interfaze.getType().getShortName() + "增加upsert方法。"); + logger.debug("itfsw(存在即更新插件):" + interfaze.getType().getShortName() + "增加upsertWithBLOBs方法。"); } // ====================================== upsertSelective ====================================== @@ -155,7 +173,7 @@ public class UpsertPlugin extends BasePlugin { commentGenerator.addGeneralMethodComment(mUpsertByExampleWithBLOBs, introspectedTable); // interface 增加方法 FormatTools.addMethodWithBestPosition(interfaze, mUpsertByExampleWithBLOBs); - logger.debug("itfsw(存在即更新插件):" + interfaze.getType().getShortName() + "增加upsertByExample方法。"); + logger.debug("itfsw(存在即更新插件):" + interfaze.getType().getShortName() + "增加upsertByExampleWithBLOBs方法。"); } // ====================================== upsertByExampleSelective ====================================== @@ -175,6 +193,55 @@ public class UpsertPlugin extends BasePlugin { } } + if (this.allowBatchUpsert) { + // ====================================== batchUpsert ====================================== + FullyQualifiedJavaType returnType = FullyQualifiedJavaType.getNewListInstance(); + returnType.addTypeArgument(JavaElementGeneratorTools.getModelTypeWithoutBLOBs(introspectedTable)); + Method mBatchUpsert = JavaElementGeneratorTools.generateMethod( + METHOD_BATCH_UPSERT, + JavaVisibility.DEFAULT, + FullyQualifiedJavaType.getIntInstance(), + new Parameter(returnType, "list", "@Param(\"list\")") + ); + commentGenerator.addGeneralMethodComment(mBatchUpsert, introspectedTable); + // interface 增加方法 + FormatTools.addMethodWithBestPosition(interfaze, mBatchUpsert); + logger.debug("itfsw(存在即更新插件):" + interfaze.getType().getShortName() + "增加batchUpsert方法。"); + + // ====================================== batchUpsertWithBLOBs ====================================== + // !!! 注意这里的行为不以有没有生成Model 的 WithBLOBs类为基准 + if (introspectedTable.hasBLOBColumns()) { + returnType = FullyQualifiedJavaType.getNewListInstance(); + returnType.addTypeArgument(JavaElementGeneratorTools.getModelTypeWithBLOBs(introspectedTable)); + Method mBatchUpsertWithBLOBs = JavaElementGeneratorTools.generateMethod( + METHOD_BATCH_UPSERT_WITH_BLOBS, + JavaVisibility.DEFAULT, + FullyQualifiedJavaType.getIntInstance(), + new Parameter(returnType, "list", "@Param(\"list\")") + ); + commentGenerator.addGeneralMethodComment(mBatchUpsertWithBLOBs, introspectedTable); + // interface 增加方法 + FormatTools.addMethodWithBestPosition(interfaze, mBatchUpsertWithBLOBs); + logger.debug("itfsw(存在即更新插件):" + interfaze.getType().getShortName() + "增加batchUpsertWithBLOBs方法。"); + } + + // ====================================== batchUpsertSelective ====================================== + returnType = FullyQualifiedJavaType.getNewListInstance(); + returnType.addTypeArgument(fullFieldModel); + FullyQualifiedJavaType selectiveType = new FullyQualifiedJavaType(introspectedTable.getRules().calculateAllFieldsClass().getShortName() + "." + ModelColumnPlugin.ENUM_NAME); + Method mBatchUpsertSelective = JavaElementGeneratorTools.generateMethod( + METHOD_BATCH_UPSERT_SELECTIVE, + JavaVisibility.DEFAULT, + FullyQualifiedJavaType.getIntInstance(), + new Parameter(returnType, "list", "@Param(\"list\")"), + new Parameter(selectiveType, "selective", "@Param(\"selective\")", true) + ); + commentGenerator.addGeneralMethodComment(mBatchUpsertSelective, introspectedTable); + // interface 增加方法 + FormatTools.addMethodWithBestPosition(interfaze, mBatchUpsertSelective); + logger.debug("itfsw(存在即更新插件):" + interfaze.getType().getShortName() + "增加batchUpsertSelective方法。"); + } + return super.clientGenerated(interfaze, topLevelClass, introspectedTable); } @@ -193,9 +260,147 @@ public class UpsertPlugin extends BasePlugin { this.generateXmlElement(document, introspectedTable, true); } + if (this.allowBatchUpsert) { + this.generateBatchXmlElementSelective(document, introspectedTable); + this.generateBatchXmlElement(document, introspectedTable, false); + if (introspectedTable.hasBLOBColumns()) { + this.generateBatchXmlElement(document, introspectedTable, true); + } + } + return super.sqlMapDocumentGenerated(document, introspectedTable); } + /** + * 批量 + * @param document + * @param introspectedTable + */ + private void generateBatchXmlElementSelective(Document document, IntrospectedTable introspectedTable) { + XmlElement insertEle = new XmlElement("insert"); + insertEle.addAttribute(new Attribute("id", METHOD_BATCH_UPSERT_SELECTIVE)); + // 添加注释(!!!必须添加注释,overwrite覆盖生成时,@see XmlFileMergerJaxp.isGeneratedNode会去判断注释中是否存在OLD_ELEMENT_TAGS中的一点,例子:@mbg.generated) + commentGenerator.addComment(insertEle); + + // 参数类型 + insertEle.addAttribute(new Attribute("parameterType", "map")); + + // 使用JDBC的getGenereatedKeys方法获取主键并赋值到keyProperty设置的领域模型属性中。所以只支持MYSQL和SQLServer + XmlElementGeneratorTools.useGeneratedKeys(insertEle, introspectedTable); + + // insert + insertEle.addElement(new TextElement("insert into " + introspectedTable.getFullyQualifiedTableNameAtRuntime() + " (")); + + XmlElement foreachInsertColumns = new XmlElement("foreach"); + foreachInsertColumns.addAttribute(new Attribute("collection", "selective")); + foreachInsertColumns.addAttribute(new Attribute("item", "column")); + foreachInsertColumns.addAttribute(new Attribute("separator", ",")); + foreachInsertColumns.addElement(new TextElement("${column.value}")); + + insertEle.addElement(foreachInsertColumns); + + insertEle.addElement(new TextElement(")")); + + // values + insertEle.addElement(new TextElement("values")); + + // foreach values + XmlElement foreachValues = new XmlElement("foreach"); + foreachValues.addAttribute(new Attribute("collection", "list")); + foreachValues.addAttribute(new Attribute("item", "item")); + foreachValues.addAttribute(new Attribute("separator", ",")); + + foreachValues.addElement(new TextElement("(")); + + // foreach 所有插入的列,比较是否存在 + XmlElement foreachInsertColumnsCheck = new XmlElement("foreach"); + foreachInsertColumnsCheck.addAttribute(new Attribute("collection", "selective")); + foreachInsertColumnsCheck.addAttribute(new Attribute("item", "column")); + foreachInsertColumnsCheck.addAttribute(new Attribute("separator", ",")); + + // 所有表字段 + List columns = ListUtilities.removeIdentityAndGeneratedAlwaysColumns(introspectedTable.getAllColumns()); + List columns1 = ListUtilities.removeIdentityAndGeneratedAlwaysColumns(introspectedTable.getAllColumns()); + for (int i = 0; i < columns1.size(); i++) { + IntrospectedColumn introspectedColumn = columns.get(i); + XmlElement check = new XmlElement("if"); + check.addAttribute(new Attribute("test", "'" + introspectedColumn.getActualColumnName() + "' == column.value")); + check.addElement(new TextElement(MyBatis3FormattingUtilities.getParameterClause(introspectedColumn, "item."))); + + foreachInsertColumnsCheck.addElement(check); + } + foreachValues.addElement(foreachInsertColumnsCheck); + + foreachValues.addElement(new TextElement(")")); + + insertEle.addElement(foreachValues); + + insertEle.addElement(new TextElement("on duplicate key update ")); + // set + XmlElement foreachSetColumns = new XmlElement("foreach"); + insertEle.addElement(foreachSetColumns); + foreachSetColumns.addAttribute(new Attribute("collection", "selective")); + foreachSetColumns.addAttribute(new Attribute("item", "column")); + foreachSetColumns.addAttribute(new Attribute("separator", ",")); + foreachSetColumns.addElement(new TextElement("${column.value} = values(${column.value})")); + + document.getRootElement().addElement(insertEle); + logger.debug("itfsw(存在即更新插件):" + introspectedTable.getMyBatis3XmlMapperFileName() + "增加batchUpsertSelective实现方法。"); + } + + /** + * 批量 + * @param document + * @param introspectedTable + * @param withBLOBs + */ + private void generateBatchXmlElement(Document document, IntrospectedTable introspectedTable, boolean withBLOBs) { + List columns = ListUtilities.removeGeneratedAlwaysColumns(withBLOBs ? introspectedTable.getAllColumns() : introspectedTable.getNonBLOBColumns()); + XmlElement insertEle = new XmlElement("insert"); + insertEle.addAttribute(new Attribute("id", withBLOBs ? METHOD_BATCH_UPSERT_WITH_BLOBS : METHOD_BATCH_UPSERT)); + // 添加注释(!!!必须添加注释,overwrite覆盖生成时,@see XmlFileMergerJaxp.isGeneratedNode会去判断注释中是否存在OLD_ELEMENT_TAGS中的一点,例子:@mbg.generated) + commentGenerator.addComment(insertEle); + + // 参数类型 + insertEle.addAttribute(new Attribute("parameterType", "map")); + + // 使用JDBC的getGenereatedKeys方法获取主键并赋值到keyProperty设置的领域模型属性中。所以只支持MYSQL和SQLServer + XmlElementGeneratorTools.useGeneratedKeys(insertEle, introspectedTable); + + // insert + insertEle.addElement(new TextElement("insert into " + introspectedTable.getFullyQualifiedTableNameAtRuntime())); + for (Element element : XmlElementGeneratorTools.generateUpsertKeys(columns, null)) { + insertEle.addElement(element); + } + insertEle.addElement(new TextElement("values")); + + // values + XmlElement foreachEle = new XmlElement("foreach"); + insertEle.addElement(foreachEle); + foreachEle.addAttribute(new Attribute("collection", "list")); + foreachEle.addAttribute(new Attribute("item", "item")); + foreachEle.addAttribute(new Attribute("separator", ",")); + + for (Element element : XmlElementGeneratorTools.generateUpsertValues(columns, "item.", true)) { + foreachEle.addElement(element); + } + insertEle.addElement(new TextElement("on duplicate key update ")); + // set + Iterator columnIterator = columns.iterator(); + while (columnIterator.hasNext()) { + IntrospectedColumn column = columnIterator.next(); + insertEle.addElement(new TextElement( + MyBatis3FormattingUtilities.getEscapedColumnName(column) + + " = values(" + MyBatis3FormattingUtilities.getEscapedColumnName(column) + + ")" + + (columnIterator.hasNext() ? "," : "") + )); + } + + document.getRootElement().addElement(insertEle); + logger.debug("itfsw(存在即更新插件):" + introspectedTable.getMyBatis3XmlMapperFileName() + "增加" + (withBLOBs ? "batchUpsertWithBLOBs" : "batchUpsert") + "实现方法。"); + } + /** * 当Selective情况 * @param document @@ -315,7 +520,7 @@ public class UpsertPlugin extends BasePlugin { } document.getRootElement().addElement(insertEle); - logger.debug("itfsw(存在即更新插件):" + introspectedTable.getMyBatis3XmlMapperFileName() + "增加upsert实现方法。"); + logger.debug("itfsw(存在即更新插件):" + introspectedTable.getMyBatis3XmlMapperFileName() + "增加" + (withBLOBs ? "upsertWithBLOBs" : "upsert") + "实现方法。"); if (this.allowMultiQueries) { // ====================================== upsertByExample ====================================== @@ -352,7 +557,7 @@ public class UpsertPlugin extends BasePlugin { this.generateExistsClause(introspectedTable, updateEle, XmlElementGeneratorTools.generateUpsertValues(columns, "record.", false)); document.getRootElement().addElement(updateEle); - logger.debug("itfsw(存在即更新插件):" + introspectedTable.getMyBatis3XmlMapperFileName() + "增加upsertByExample实现方法。"); + logger.debug("itfsw(存在即更新插件):" + introspectedTable.getMyBatis3XmlMapperFileName() + "增加" + (withBLOBs ? "upsertByExampleWithBLOBs" : "upsertByExample") + "实现方法。"); } } 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 ea5e0aa..a848382 100644 --- a/src/test/java/com/itfsw/mybatis/generator/plugins/BatchInsertPluginTest.java +++ b/src/test/java/com/itfsw/mybatis/generator/plugins/BatchInsertPluginTest.java @@ -147,7 +147,7 @@ public class BatchInsertPluginTest { @Test public void testBatchInsert() throws Exception { MyBatisGeneratorTool tool = MyBatisGeneratorTool.create("scripts/BatchInsertPlugin/mybatis-generator.xml"); - tool.generate(new AbstractShellCallback() { + tool.generate(() -> DBHelper.resetDB("scripts/BatchInsertPlugin/init.sql"), new AbstractShellCallback() { @Override public void reloadProject(SqlSession sqlSession, ClassLoader loader, String packagz) throws Exception { // 1. 测试sql @@ -184,7 +184,7 @@ public class BatchInsertPluginTest { @Test public void testBatchInsertSelective() throws Exception { MyBatisGeneratorTool tool = MyBatisGeneratorTool.create("scripts/BatchInsertPlugin/mybatis-generator.xml"); - tool.generate(new AbstractShellCallback() { + tool.generate(() -> DBHelper.resetDB("scripts/BatchInsertPlugin/init.sql"), new AbstractShellCallback() { @Override public void reloadProject(SqlSession sqlSession, ClassLoader loader, String packagz) throws Exception { // 1. 测试sql diff --git a/src/test/java/com/itfsw/mybatis/generator/plugins/UpsertPluginTest.java b/src/test/java/com/itfsw/mybatis/generator/plugins/UpsertPluginTest.java index bbc0044..6010fe2 100644 --- a/src/test/java/com/itfsw/mybatis/generator/plugins/UpsertPluginTest.java +++ b/src/test/java/com/itfsw/mybatis/generator/plugins/UpsertPluginTest.java @@ -25,8 +25,11 @@ import org.mybatis.generator.exception.InvalidConfigurationException; import org.mybatis.generator.exception.XMLParserException; import java.io.IOException; +import java.lang.reflect.Array; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; /** * --------------------------------------------------------------------------- @@ -41,7 +44,7 @@ public class UpsertPluginTest { * 初始化 */ @BeforeClass - public static void init() throws Exception{ + public static void init() throws Exception { DBHelper.createDB("scripts/UpsertPlugin/init.sql"); } @@ -421,4 +424,136 @@ public class UpsertPluginTest { } }); } + + /** + * 测试批量batchUpsert + */ + @Test + public void testBatchUpsert() throws Exception { + MyBatisGeneratorTool tool = MyBatisGeneratorTool.create("scripts/UpsertPlugin/mybatis-generator-with-allowBatchUpsert.xml"); + tool.generate(() -> DBHelper.resetDB("scripts/UpsertPlugin/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("id", 1L).set("field1", "ts1").getObject()); + params.add(new ObjectUtil(loader, packagz + ".Tb").set("id", 6L).set("field1", "ts2").set("field2", 1).getObject()); + + String sql = SqlHelper.getFormatMapperSql(tbMapper.getObject(), "batchUpsert", params); + Assert.assertEquals(sql, "insert into tb (id, field1, field2) values (1, 'ts1', null ) , (6, 'ts2', 1 ) on duplicate key update id = values(id), field1 = values(field1), field2 = values(field2)"); + // 2. 执行sql + Object count = tbMapper.invoke("batchUpsert", params); + Assert.assertEquals(count, 3); + + // 验证 + ResultSet rs = DBHelper.execute(sqlSession, "select * from tb where id = 1"); + rs.first(); + Assert.assertEquals(rs.getString("field1"), "ts1"); + + rs = DBHelper.execute(sqlSession, "select * from tb where id = 6"); + rs.first(); + Assert.assertEquals(rs.getString("field1"), "ts2"); + } + }); + } + + /** + * 测试批量batchUpsertWithBLOBs + */ + @Test + public void testBatchUpsertWithBLOBs() throws Exception { + // 1. batchUpsert + MyBatisGeneratorTool tool = MyBatisGeneratorTool.create("scripts/UpsertPlugin/mybatis-generator-with-allowBatchUpsert.xml"); + tool.generate(() -> DBHelper.resetDB("scripts/UpsertPlugin/init.sql"), new AbstractShellCallback() { + @Override + public void reloadProject(SqlSession sqlSession, ClassLoader loader, String packagz) throws Exception { + ObjectUtil tbBlobsMapper = new ObjectUtil(sqlSession.getMapper(loader.loadClass(packagz + ".TbBlobsMapper"))); + List params = new ArrayList<>(); + params.add(new ObjectUtil(loader, packagz + ".TbBlobs").set("id", 1L).set("field1", "ts1").getObject()); + params.add(new ObjectUtil(loader, packagz + ".TbBlobs").set("id", 6L).set("field1", "ts2").getObject()); + + String sql = SqlHelper.getFormatMapperSql(tbBlobsMapper.getObject(), "batchUpsert", params); + Assert.assertEquals(sql, "insert into tb_blobs (id, field1) values (1, 'ts1') , (6, 'ts2') on duplicate key update id = values(id), field1 = values(field1)"); + // 2. 执行sql + Object count = tbBlobsMapper.invoke("batchUpsert", params); + Assert.assertEquals(count, 3); + + // 验证 + ResultSet rs = DBHelper.execute(sqlSession, "select * from tb_blobs where id = 1"); + rs.first(); + Assert.assertEquals(rs.getString("field1"), "ts1"); + + rs = DBHelper.execute(sqlSession, "select * from tb_blobs where id = 6"); + rs.first(); + Assert.assertEquals(rs.getString("field1"), "ts2"); + } + }); + + // 2. batchUpsertWithBLOBs + tool.generate(() -> DBHelper.resetDB("scripts/UpsertPlugin/init.sql"), new AbstractShellCallback() { + @Override + public void reloadProject(SqlSession sqlSession, ClassLoader loader, String packagz) throws Exception { + ObjectUtil tbBlobsMapper = new ObjectUtil(sqlSession.getMapper(loader.loadClass(packagz + ".TbBlobsMapper"))); + List params = new ArrayList<>(); + params.add(new ObjectUtil(loader, packagz + ".TbBlobsWithBLOBs").set("id", 1L).set("field1", "ts1").set("field3", "ff1").getObject()); + params.add(new ObjectUtil(loader, packagz + ".TbBlobsWithBLOBs").set("id", 6L).set("field1", "ts2").set("field3", "ff2").getObject()); + + String sql = SqlHelper.getFormatMapperSql(tbBlobsMapper.getObject(), "batchUpsertWithBLOBs", params); + Assert.assertEquals(sql, "insert into tb_blobs (id, field1, field2, field3) values (1, 'ts1', 'null', 'ff1') , (6, 'ts2', 'null', 'ff2') on duplicate key update id = values(id), field1 = values(field1), field2 = values(field2), field3 = values(field3)"); + // 2. 执行sql + Object count = tbBlobsMapper.invoke("batchUpsertWithBLOBs", params); + Assert.assertEquals(count, 3); + + // 验证 + ResultSet rs = DBHelper.execute(sqlSession, "select * from tb_blobs where id = 1"); + rs.first(); + Assert.assertEquals(rs.getString("field1"), "ts1"); + Assert.assertEquals(rs.getString("field3"), "ff1"); + + rs = DBHelper.execute(sqlSession, "select * from tb_blobs where id = 6"); + rs.first(); + Assert.assertEquals(rs.getString("field1"), "ts2"); + Assert.assertEquals(rs.getString("field3"), "ff2"); + } + }); + } + + /** + * 测试批量batchUpsertSelective + */ + @Test + public void testBatchUpsertSelective() throws Exception { + MyBatisGeneratorTool tool = MyBatisGeneratorTool.create("scripts/UpsertPlugin/mybatis-generator-with-allowBatchUpsert.xml"); + tool.generate(() -> DBHelper.resetDB("scripts/UpsertPlugin/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("id", 1L).set("field1", "ts1").getObject()); + params.add(new ObjectUtil(loader, packagz + ".Tb").set("id", 6L).set("field1", "ts2").set("field2", 1).getObject()); + + ObjectUtil columnId = new ObjectUtil(loader, packagz + ".Tb$Column#id"); + ObjectUtil columnField1 = new ObjectUtil(loader, packagz + ".Tb$Column#field1"); + Object columns = Array.newInstance(columnId.getCls(), 2); + Array.set(columns, 0, columnId.getObject()); + Array.set(columns, 1, columnField1.getObject()); + + String sql = SqlHelper.getFormatMapperSql(tbMapper.getObject(), "batchUpsertSelective", params, columns); + Assert.assertEquals(sql, "insert into tb ( id , field1 ) values ( 1 , 'ts1' ) , ( 6 , 'ts2' ) on duplicate key update id = values(id) , field1 = values(field1)"); + // 2. 执行sql + Object count = tbMapper.invoke("batchUpsertSelective", params, columns); + Assert.assertEquals(count, 3); + + // 验证 + ResultSet rs = DBHelper.execute(sqlSession, "select * from tb where id = 1"); + rs.first(); + Assert.assertEquals(rs.getString("field1"), "ts1"); + + rs = DBHelper.execute(sqlSession, "select * from tb where id = 6"); + rs.first(); + Assert.assertEquals(rs.getString("field1"), "ts2"); + Assert.assertNull(rs.getString("field2")); + } + }); + } } diff --git a/src/test/resources/scripts/UpsertPlugin/init.sql b/src/test/resources/scripts/UpsertPlugin/init.sql index 0a80ff5..fcf4637 100644 --- a/src/test/resources/scripts/UpsertPlugin/init.sql +++ b/src/test/resources/scripts/UpsertPlugin/init.sql @@ -48,6 +48,9 @@ CREATE TABLE `tb_blobs` ( -- ---------------------------- -- Records of tb_blobs -- ---------------------------- +INSERT INTO `tb_blobs` VALUES ('1', 'fd1', null, 'KK1'); +INSERT INTO `tb_blobs` VALUES ('2', null, '2', null); +INSERT INTO `tb_blobs` VALUES ('3', 'fd3', '3', 'KK3'); -- ---------------------------- -- Table structure for tb_keys diff --git a/src/test/resources/scripts/UpsertPlugin/mybatis-generator-with-allowBatchUpsert.xml b/src/test/resources/scripts/UpsertPlugin/mybatis-generator-with-allowBatchUpsert.xml new file mode 100644 index 0000000..2e23efd --- /dev/null +++ b/src/test/resources/scripts/UpsertPlugin/mybatis-generator-with-allowBatchUpsert.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ +
+ + +
+
+
\ No newline at end of file