【发布时间】:2019-02-05 15:40:41
【问题描述】:
我需要更新 DB2 数据库中超过 1000000 条记录。 我尝试将休眠与多线程应用程序一起使用来更新记录。但是,这样做我得到了 lockacquisitionexception。我觉得这是因为我与多个线程一起进行的批量提交。 有人可以推荐一个更好的解决方案或更好的方法。 如果我需要上传我正在使用的代码,请告诉我。 提前致谢。
//Code running multiple times with threads
Transaction tx = null;
tx = session.beginTransaction();
for(EncryptRef abc : arList) {
String encrypted = keyUtils.encrypt(abc.getNumber()); //to encrypt some data
Object o = session.load(EncryptRef.class,new Long(abc.getId())); //primary key EncryptRef object = (EncryptRef)o;
object.setEncryptedNumber(encrypted); //updating the row
}
tx.commit(); //bulk commiting the updates
表只包含三列。 ID|纯文本|加密文本
更新: 我尝试使用 JDBC 准备语句进行批量更新。但是,我仍然面临以下异常:
com.ibm.db2.jcc.am.BatchUpdateException: [jcc][t4][102][10040][3.63.75] 批处理失败。该批次是 已提交,但至少有一个例外发生在个别成员身上 该批次的。使用 getNextException() 检索异常 特定的批处理元素。 ERRORCODE=-4229,SQLSTATE=null 在 com.ibm.db2.jcc.am.fd.a(fd.java:407) 在 com.ibm.db2.jcc.am.n.a(n.java:386) 在 com.ibm.db2.jcc.am.zn.a(zn.java:4897) 在 com.ibm.db2.jcc.am.zn.c(zn.java:4528) 在 com.ibm.db2.jcc.am.zn.executeBatch(zn.java:2837) 在 org.npci.ThreadClass.run(ThreadClass.java:63) 在 java.lang.Thread.run(Thread.java:748)
以下是批处理大小为 50-100 条记录的代码:
String queryToUpdate = "UPDATE INST1.ENCRYPT_REF SET ENCR_NUM=? WHERE ID=?";
PreparedStatement pstmtForUpdate = conn.prepareStatement(queryToUpdate);
for (Map.Entry<Long,String> entry : encryptMap.entrySet()) {
pstmtForUpdate.setString(1, entry.getValue());
pstmtForUpdate.setLong(2, entry.getKey());
pstmtForUpdate.addBatch();
}
pstmtForUpdate.executeBatch();
conn.close();
【问题讨论】:
-
最好描述您使用的更新逻辑,并指定您是否能够在单个事务中执行此操作(您必须具有适当的事务日志大小)。
-
另外,您应该描述操作要求。具体来说,批量更新运行时的并发要求。确保 Hibernate 生成的 UPDATE(或 MERGE)语句被索引,并且使用了合适的隔离级别。如果要更新的列被索引,或者是外键,或者有触发器,那么可能会应用不同的建议。 SO:您的问题太模糊,无法得到具体答案。
-
运行此代码时,Hibernate 是否会先选择行,然后再更新它? (如果您还没有打开 SQL 日志记录。)您实际上并没有访问对象中的任何字段,因此无需读取它。一般来说,Hibernate 是一种糟糕的方式来进行这些更新;最好只使用 SQL。
-
我也尝试了 JDBC 准备语句。但没有运气。更新了代码供参考。
标签: java hibernate exception db2