fixed: oracle insert batch error

This commit is contained in:
开源海哥 2023-06-08 09:41:24 +08:00
parent fcd5a58f90
commit b2fcb88ca8
4 changed files with 177 additions and 3 deletions

View File

@ -66,7 +66,7 @@ public interface IDialect {
//////for entity /////
String forInsertEntity(TableInfo tableInfo, Object entity, boolean ignoreNulls);
String forInsertEntityBatch(TableInfo tableInfo, List<Object> entities);
String forInsertEntityBatch(TableInfo tableInfo, List<?> entities);
String forDeleteEntityById(TableInfo tableInfo);

View File

@ -415,7 +415,7 @@ public class CommonsDialectImpl implements IDialect {
}
@Override
public String forInsertEntityBatch(TableInfo tableInfo, List<Object> 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);

View File

@ -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<String, String> 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<Row> 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<String> 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();
}
}

View File

@ -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<Account> 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<Row> 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);
}
}