我是一个学习Hibernate的新手,在弄清刷新一批记录时出现的异常的正确处理方法时遇到了一些困难。 我的程序从阻塞队列中获取文件,并将其持久保存到数据库中。我每刷新10个文件,每提交250个文件就提交这些记录。隔离级别已提交。
请注意,该程序通过ThreadPoolExecutor使用并行线程。通过应该是线程安全的包装器来创建/维护会话。
所以这里有一些简化的代码来说明:
for (int i = localI.get(); i<10000000; localI.set(i++)) {
File take = bqueue.poll(30000, TimeUnit.MILLISECONDS);
if (take == null) {
break;
}
fp = new fileParser(String.valueOf(take));
data d = fp.get();
if(currentFiles.get()==null) { currentFiles.set(new ArrayList<BidiMap<String, String>>()); }
BidiMap<String, String> m = new DualHashBidiMap<>();
m.put(String.valueOf(d.getId()), "id");
m.put(String.valueOf(take), "fileName");
m.put(d.getHwAssetTag(), "hwAssetTag");
currentFiles.get().add(m);
session.persist(data)
if ( (i > 0 && i % 10 == 0) ) {
try {
session.flush();
session.clear();
} catch (PersistenceException e) {
rollBackAndRetry(currentFiles);
}
}
currentFiles.set(null);
take = null;
if (i == 250) {
try {
session.flush();
session.clear();
session.commit();
} catch (PersistenceException e) {
Logger.info("Error occured while trying to commit batch!");
} finally {
session.close()
localI.set(1);
}
}
}
因此从队列中获取一条记录。获取我想要的数据并坚持下去。 我正在使用双向映射列表来跟踪批处理中的项目,以便在出现问题时尝试单独提交记录。
可以通过以下方法处理:
public void rollBackAndRetry(ThreadLocal<java.util.List<BidiMap<String, String>>> list) {
BidiMap<String, String> m = new DualHashBidiMap<>();
ThreadLocal<Integer> ii = new ThreadLocal<>();
ii.set(0);
try {
for (int i = ii.get(); i<list.get().size(); ii.set(i++)) {
m = list.get().get(i);
int id = Integer.parseInt(m.getKey("id"));
String fileName = m.getKey("fileName");
String hwAssetTag = m.getKey("hwAssetTag");
data ss = fp.get();
try {
Boolean removed = deleteById(data.class, id);
if (removed) {
session.flush();
session.merge(ss);
session.flush();
} else {
Logger.error("Something happened trying to remove data for " + hwAssetTag);
}
} catch (PersistenceException ee) {
Logger.error("Error saving data for record " + hwAssetTag + ": " + ee);
}
}
} catch (PersistenceException e) {
Logger.error("Error " + e + " occured");
} finally {
m = null;
ii = null;
}
}
这是我有点困惑的地方。我不确定如何实际处理尝试刷新的数据。我的想法是,由于刷新失败,它仍位于1级缓存中,因此我应该能够删除/分离/删除/删除它?
private boolean deleteById(Class<?> type, Serializable id) {
Boolean result = false;
try {
Object persistentInstance = session.load(type, id);
if (persistentInstance != null) {
session.delete(persistentInstance);
session.detach(persistentInstance);
session.remove(persistentInstance);
result = true;
}
} catch (PersistenceException | IllegalArgumentException e) {
Logger.error("An error occured trying to remove id " + id + " " + e);
}
return result;
}
到目前为止,我还无法弄清楚如何删除与最后一批10相关的实体。它不应该像detach(),remove()和flush()一样简单吗? 我遇到的异常范围从“约束违规”错误(因为未正确删除1级缓存中的数据)到我最近的头痛:ERROR org.hibernate.AssertionFailure-HHH000099:发生断言失败
对我的方法有任何想法吗?我想知道我是否应该尝试每10条记录而不是刷新一次commit(),因为无论如何我都处于读取提交模式。
提前感谢您可以分享的任何见解。