diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/IDialect.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/IDialect.java index e7fcfa43..b31848f5 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/IDialect.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/IDialect.java @@ -66,7 +66,7 @@ public interface IDialect { //////for entity ///// String forInsertEntity(TableInfo tableInfo, Object entity, boolean ignoreNulls); - String forInsertEntityBatch(TableInfo tableInfo, List entities); + String forInsertEntityBatch(TableInfo tableInfo, List entities); String forDeleteEntityById(TableInfo tableInfo); diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/impl/CommonsDialectImpl.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/impl/CommonsDialectImpl.java index 59d483d9..d7f21ec8 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/impl/CommonsDialectImpl.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/impl/CommonsDialectImpl.java @@ -415,7 +415,7 @@ public class CommonsDialectImpl implements IDialect { } @Override - public String forInsertEntityBatch(TableInfo tableInfo, List entities) { + public String forInsertEntityBatch(TableInfo tableInfo, List entities) { StringBuilder sql = new StringBuilder(); sql.append("INSERT INTO ").append(tableInfo.getWrapSchemaAndTableName(this)); String[] insertColumns = tableInfo.obtainInsertColumns(null, false); diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/impl/OracleDialect.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/impl/OracleDialect.java index b452148a..9b21f370 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/impl/OracleDialect.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/impl/OracleDialect.java @@ -17,9 +17,15 @@ package com.mybatisflex.core.dialect.impl; import com.mybatisflex.core.dialect.KeywordWrap; import com.mybatisflex.core.dialect.LimitOffsetProcessor; +import com.mybatisflex.core.row.Row; +import com.mybatisflex.core.table.TableInfo; import com.mybatisflex.core.util.CollectionUtil; +import com.mybatisflex.core.util.StringUtil; +import java.util.List; +import java.util.Map; import java.util.Set; +import java.util.StringJoiner; public class OracleDialect extends CommonsDialectImpl { @@ -56,8 +62,92 @@ public class OracleDialect extends CommonsDialectImpl { public OracleDialect() { this(LimitOffsetProcessor.ORACLE); } + public OracleDialect(LimitOffsetProcessor limitOffsetProcessor) { - super(new KeywordWrap(keywords,"\"","\""),limitOffsetProcessor); + super(new KeywordWrap(keywords, "\"", "\""), limitOffsetProcessor); } + @Override + public String forInsertEntityBatch(TableInfo tableInfo, List entities) { + /** + * INSERT ALL + * INTO t (col1, col2, col3) VALUES ('val1_1', 'val1_2', 'val1_3') + * INTO t (col1, col2, col3) VALUES ('val2_1', 'val2_2', 'val2_3') + * INTO t (col1, col2, col3) VALUES ('val3_1', 'val3_2', 'val3_3') + * . + * . + * . + * SELECT 1 FROM DUAL; + */ + StringBuilder sql = new StringBuilder(); + sql.append("INSERT ALL"); + String[] insertColumns = tableInfo.obtainInsertColumns(null, false); + String[] warpedInsertColumns = new String[insertColumns.length]; + for (int i = 0; i < insertColumns.length; i++) { + warpedInsertColumns[i] = wrap(insertColumns[i]); + } + + + Map onInsertColumns = tableInfo.getOnInsertColumns(); + for (int i = 0; i < entities.size(); i++) { + sql.append(" INTO ").append(tableInfo.getWrapSchemaAndTableName(this)); + sql.append(" (").append(StringUtil.join(", ", warpedInsertColumns)).append(")"); + sql.append(" VALUES "); + + StringJoiner stringJoiner = new StringJoiner(", ", "(", ")"); + for (String insertColumn : insertColumns) { + if (onInsertColumns != null && onInsertColumns.containsKey(insertColumn)) { + //直接读取 onInsert 配置的值,而不用 "?" 代替 + stringJoiner.add(onInsertColumns.get(insertColumn)); + } else { + stringJoiner.add("?"); + } + } + sql.append(stringJoiner); + } + + return sql.append(" SELECT 1 FROM DUAL").toString(); + } + + + @Override + public String forInsertBatchWithFirstRowColumns(String schema, String tableName, List rows) { + /** + * INSERT ALL + * INTO t (col1, col2, col3) VALUES ('val1_1', 'val1_2', 'val1_3') + * INTO t (col1, col2, col3) VALUES ('val2_1', 'val2_2', 'val2_3') + * INTO t (col1, col2, col3) VALUES ('val3_1', 'val3_2', 'val3_3') + * . + * . + * . + * SELECT 1 FROM DUAL; + */ + StringBuilder fields = new StringBuilder(); + Row firstRow = rows.get(0); + Set attrs = firstRow.obtainModifyAttrs(); + int index = 0; + for (String column : attrs) { + fields.append(wrap(column)); + if (index != attrs.size() - 1) { + fields.append(", "); + } + index++; + } + + StringBuilder sql = new StringBuilder(); + sql.append("INSERT ALL"); + + String tableNameWrap = StringUtil.isNotBlank(schema) + ? wrap(getRealSchema(schema)) + "." + wrap(getRealTable(tableName)) + : wrap(getRealTable(tableName)); + String questionStrings = buildQuestion(attrs.size(), true); + + for (int i = 0; i < rows.size(); i++) { + sql.append(" INTO ").append(tableNameWrap); + sql.append(" (").append(fields).append(")"); + sql.append(" VALUES ").append(questionStrings); + } + + return sql.append(" SELECT 1 FROM DUAL").toString(); + } } diff --git a/mybatis-flex-core/src/test/java/com/mybatisflex/coretest/OracleDialectTester.java b/mybatis-flex-core/src/test/java/com/mybatisflex/coretest/OracleDialectTester.java new file mode 100644 index 00000000..e875716e --- /dev/null +++ b/mybatis-flex-core/src/test/java/com/mybatisflex/coretest/OracleDialectTester.java @@ -0,0 +1,84 @@ +package com.mybatisflex.coretest; + +import com.mybatisflex.core.dialect.IDialect; +import com.mybatisflex.core.dialect.impl.OracleDialect; +import com.mybatisflex.core.query.QueryWrapper; +import com.mybatisflex.core.row.Row; +import com.mybatisflex.core.table.TableInfoFactory; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static com.mybatisflex.coretest.table.AccountTableDef.ACCOUNT; + +public class OracleDialectTester { + + + @Test + public void testSelectSql() { + QueryWrapper query = new QueryWrapper() + .select() + .from(ACCOUNT); + + IDialect dialect = new OracleDialect(); + String sql = dialect.forSelectByQuery(query); + System.out.println(sql); + } + + @Test + public void testInsertBatchSql() { + List accounts = new ArrayList<>(); + Account account1 = new Account(); + account1.setUserName("michael1"); + account1.setAge(18); + account1.setSex(1); + accounts.add(account1); + + Account account2 = new Account(); + account2.setUserName("michael2"); + account2.setAge(19); + account2.setSex(2); + accounts.add(account2); + + Account account3 = new Account(); + account3.setUserName("michael3"); + account3.setAge(20); + account3.setSex(3); + accounts.add(account3); + + + IDialect dialect = new OracleDialect(); + String sql = dialect.forInsertEntityBatch(TableInfoFactory.ofEntityClass(Account.class),accounts); + System.out.println(sql); + } + + + @Test + public void testInsertRowBatchSql() { + List accounts = new ArrayList<>(); + Row account1 = new Row(); + account1.set("username","michael1"); + account1.set("age",18); + account1.set("sex",1); + accounts.add(account1); + + Row account2 = new Row(); + account2.set("username","michael2"); + account2.set("age",18); + account2.set("sex",1); + accounts.add(account2); + + Row account3 = new Row(); + account3.set("username","michael3"); + account3.set("age",18); + account3.set("sex",1); + accounts.add(account3); + + + IDialect dialect = new OracleDialect(); + String sql = dialect.forInsertBatchWithFirstRowColumns(null,"tb_account",accounts); + System.out.println(sql); + } + +}