批量保存时如果数据库某个字段设置唯一索引,在插入时会导致整个列表都插入失败,希望后边的版本添加支持;
目前临时解决方案,大部分是源码,有轻微改动:
public class DbProUtil {
/**
*
* @param db 数据库别名
* @param tableName 表名
* @param recordList 数据集合
* @param batchSize 一次插入数据数量
* @return 受影响行数
*/
public int[] ignoreBatchSave(String db, String tableName, List<Record> recordList, int batchSize) {
if (recordList == null || recordList.size() == 0) {
return new int[0];
}
Record record = recordList.get(0);
Map<String, Object> cols = record.getColumns();
int index = 0;
StringBuilder columns = new StringBuilder();
// the same as the iterator in Dialect.forDbSave() to ensure the order of the columns
for (Map.Entry<String, Object> e : cols.entrySet()) {
if (index++ > 0) {
columns.append(',');
}
columns.append(e.getKey());
}
String[] pKeysNoUse = new String[0];
StringBuilder sql = new StringBuilder();
List<Object> parasNoUse = new ArrayList<Object>();
forDbSave(tableName, pKeysNoUse, record, sql, parasNoUse);
return Db.use(db).batch(sql.toString(), columns.toString(), recordList, batchSize);
}
/**
* Do not delete the String[] pKeys parameter, the element of pKeys needs to trim()
*/
private void forDbSave(String tableName, String[] pKeys, Record record, StringBuilder sql, List<Object> paras) {
tableName = tableName.trim();
trimPrimaryKeys(pKeys); // important
sql.append("insert ignore into `");
sql.append(tableName).append("`(");
StringBuilder temp = new StringBuilder();
temp.append(") values(");
for (Map.Entry<String, Object> e: record.getColumns().entrySet()) {
if (paras.size() > 0) {
sql.append(", ");
temp.append(", ");
}
sql.append('`').append(e.getKey()).append('`');
temp.append('?');
paras.add(e.getValue());
}
sql.append(temp.toString()).append(')');
}
/**
* 一、forDbXxx 系列方法中若有如下两种情况之一,则需要调用此方法对 pKeys 数组进行 trim():
* 1:方法中调用了 isPrimaryKey(...):为了防止在主键相同情况下,由于前后空串造成 isPrimaryKey 返回 false
* 2:为了防止 tableName、colName 与数据库保留字冲突的,添加了包裹字符的:为了防止串包裹区内存在空串
* 如 mysql 使用的 "`" 字符以及 PostgreSql 使用的 "\"" 字符
* 不满足以上两个条件之一的 forDbXxx 系列方法也可以使用 trimPrimaryKeys(...) 方法让 sql 更加美观,但不是必须
*
* 二、forModelXxx 由于在映射时已经trim(),故不再需要调用此方法
*/
private void trimPrimaryKeys(String[] pKeys) {
for (int i=0; i<pKeys.length; i++) {
pKeys[i] = pKeys[i].trim();
}
}
}
项目:JFinal