【发布时间】:2019-03-28 15:11:41
【问题描述】:
我需要将批量插入到 Oracle 数据库中,但我对如何进行批量操作感到困惑。
String INSERT = "INSERT INTO LOGS(METHOD,USER,START_DATE,RESPONSE_TIME,IS_ERROR) VALUES (?,?,?,?,?)";
private synchronized void saveToDBAndClear(ConcurrentHashMap<Long, Logs> logs) {
List<Logs> list = new ArrayList<>(logs.values());
logService.insertLog(list);
initLogMap();
}
public void insertLog(List<Logs> logsList) {
int[] insertedLog = jdbcTemplate.batchUpdate(INSERT, new BatchPreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
ps.setString(1, logsList.get(i).getMethod());
ps.setString(2, logsList.get(i).getUser());
ps.setTimestamp(3, logsList.get(i).getStartDate());
ps.setLong(4, logsList.get(i).getResponseTime());
ps.setString(5, logsList.get(i).getIsError());
}
@Override
public int getBatchSize() {
return logsList.size();
}
});
logger.info("It was inserted {} logs into Logs", insertedLog.length);
}
我必须这样做
List<Logs> list = new ArrayList<>(logs.values());
因为我不知道怎么用jdbcTemplate.batchUpdate()
对于每个ConcurrentHashMap 并收集 100 或 1000 卷中的批次以推送到数据库中。
有人可以帮我吗?
附言
我试过了
public class LogProcessor {
private int batchSize = 10;
private final double initialCapacity = 1.26;
private ConcurrentHashMap<Long, Logs> logMap;
private AtomicLong logMapSize;
private void initLogMap() {
this.logMap = new ConcurrentHashMap<>((int) (batchSize * initialCapacity));
this.logMapSize = new AtomicLong();
}
public void process(LogKeeper keeper){
LogHandler log = keeper.getLog();
Long i = logMapSize.incrementAndGet();
logMap.put(i, log.toJdbc());
System.out.println("Lines inside the map = "+logMap.size());
if (i % batchSize == 0) {
System.out.println("Reached batchSize and = " + batchSize);
saveToDBAndClear(logMap);
}
private synchronized void saveToDBAndClear(ConcurrentHashMap<Long, Logs> logs) {
List<Logs> list = new ArrayList<>(logs.values());
System.out.println("Created list with size = "+ list.size());
logService.insertLog(list);
initLogMap();
System.out.println("Now size of map = "+ logs.size()+" and AtomicLong = "+logMapSize.intValue() );
}
@TransactionalRollback
public void insertLog(List<Logs> logsList) {
System.out.println("Inside insertLog method");
int[][] insertedLog=jdbcTemplate.batchUpdate(INSERT, logsList, 15, (ps, arg) -> {
ps.setString(1, arg.getMethod());
ps.setString(2, arg.getClient());
ps.setTimestamp(3, arg.getStartDate());
ps.setLong(4, arg.getResponseTime());
ps.setString(5, arg.getIsError());
});
System.out.println("It was inserted " + insertedLog[0].length + " logs into DB");
}
}
现在,如您所见。我作为私有字段的 batchSize 是 10。在 batchUpdate 中,我输入了 15。我想,如果我发送到 insertLog 方法列表,例如大小等于 1 或 100,它将收集到大小等于 15 的批次并将发送到DB,但只插入列表包含的那个卷。
因此,我必须在我的 Map 中准确收集我需要的 batchSize,然后将其发送到 insertLog 方法。如果可以的话,我只会将 Logs 日志发送到 insertLog 方法并放入类似
的内容 public void insertLog(Logs logs){
jdbcTemplate.batchUpdate(INSERT, logs, 1000, (ps, arg) ->(...));}
在那之后有人可以帮助那个bathSize插入吗?是否可以在没有像 10%batchSize=0 这样的简单验证的情况下进行 batchInsert 或 batchUpdate ?
【问题讨论】:
-
如果您要问如何以 1000 个为单位执行更新,您是否考虑过使用
batchUpdate(java.lang.String sql, java.util.Collection<T> batchArgs, int batchSize, ParameterizedPreparedStatementSetter<T> pss)重载? -
@Andreas 如果我找到了correct 那么这不是我要找的。我尝试
public void insertLog(List<Logs> logsList) { jdbcTemplate.batchUpdate(INSERT, list, 15, (ps,arg)->{ ps.setString(1, arg.getMethod()); ps.setString(2, arg.getClient()); } });它插入了 10 个,再插入 10 个,再插入 10 个元素,它们在列表中,而不是像我想的那样收集 15 行。无论如何,我不能插入到 batchUpdate 我的对象中,我必须在那里插入任何 Collection -
你怎么知道它一次插入 10 个,而不是 15 个? --- 鉴于它不应该“收集”任何东西,你所说的 “不收集 15 行”是什么意思? --- 你说的“我不能插入batchUpdate我的对象,我必须插入任何集合”是什么意思?您的代码使用集合 (
logsList)。新代码可以直接使用logs.values(),而无需先转换为List,但其他方面相同。 -
关于转换为列表,u
re correct. ---_How do you know it insert 10 at a time, not 15?_ I have logger.info(...) about it, and I see, that it was inserted 10 rows, but not 15. Now, I collect batch in Map, till the count of logs less than 100 likelogs%100=0` 但我想在 Oracle 级别制作 batchUpdate(....logs.value, 100) 并在该方法中,或者jdbc 或 jpa,它应该在内存中收集我的值(行),当它达到 100 时,它将发送到 DB -
仍然不知道你在说什么“收集”任何东西。您已经在
logsList中收集您需要的一切。然后,您使用该列表调用batchUpdate的 4 参数版本,要求它一次批量更新 15 个。编辑问题并显示您尝试过的代码,并包括(子集)创建的日志,显示它一次只批处理 10 个,因为我看不出这是怎么发生的,因为您没有收到通知它执行一个批处理,但由于我看不到你做了什么,所以很难说。