批量保存时如果数据库某个字段设置唯一索引,在插入时会导致整个列表都插入失败,希望后边的版本添加支持;
目前临时解决方案,大部分是源码,有轻微改动:
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