我想要获取Relation记录的列表,我将使用.fetchInto(RELATION);
,并且我想遍历列表并将每次迭代提交到数据库。这似乎对我不起作用,因为我在更新记录时得到Caused by: java.sql.SQLException: Connection is closed
。对于常规jOOQ查询,我没有这个问题。而且似乎没有任何连接是关闭的。
当我使用contact.attach(jooq().configuration())
时,它似乎又工作了。我怎样才能防止它脱落呢?
我通过JPA.em().getTransaction().*
启动并提交一个事务。
org.jooq.exception.DataAccessException: SQL [update `Relation` set `Relation`.`organizationName` = ? where `Relation`.`id` = ?]; Connection is closed
at org.jooq_3.15.1.MYSQL.debug(Unknown Source)
at org.jooq.impl.Tools.translate(Tools.java:2979)
at org.jooq.impl.DefaultExecuteContext.sqlException(DefaultExecuteContext.java:643)
at org.jooq.impl.AbstractQuery.execute(AbstractQuery.java:349)
at org.jooq.impl.UpdatableRecordImpl.storeMergeOrUpdate0(UpdatableRecordImpl.java:331)
at org.jooq.impl.UpdatableRecordImpl.storeUpdate0(UpdatableRecordImpl.java:228)
at org.jooq.impl.UpdatableRecordImpl.lambda$storeUpdate$1(UpdatableRecordImpl.java:220)
at org.jooq.impl.RecordDelegate.operate(RecordDelegate.java:143)
at org.jooq.impl.UpdatableRecordImpl.storeUpdate(UpdatableRecordImpl.java:219)
at org.jooq.impl.UpdatableRecordImpl.update(UpdatableRecordImpl.java:156)
at org.jooq.impl.UpdatableRecordImpl.update(UpdatableRecordImpl.java:151)
at worker.taskprocessors.BulkContactEditWorker.execute(BulkContactEditWorker.java:144)
的例子:
var contacts = jooq()
.selectFrom(
RELATION
.join(BULK_CONTACT_EDIT_CONTACTS)
.on(
BULK_CONTACT_EDIT_CONTACTS
.CONTACT_ID
.eq(RELATION.ID)
.and(BULK_CONTACT_EDIT_CONTACTS.BULK_CONTACT_EDIT_ID.eq(bulkContactEditId))
.and(BULK_CONTACT_EDIT_CONTACTS.PROCESSED.isFalse())))
.limit(batchSize)
.fetchInto(RELATION);
if (!JPA.em().getTransaction().isActive()) {
JPA.em().getTransaction().begin();
}
for (RelationRecord contact : contacts) {
contact.attach(jooq().configuration()); // I have to add this line to make it work.
contact.setOrganizationName("OrganizationName");
contact.update();
JPA.em().getTransaction().commit();
if (!JPA.em().getTransaction().isActive()) {
JPA.em().getTransaction().begin();
}
}
有什么问题
您正在JPA事务上下文之外获取jOOQRelationRecord
值,因此获取在其自己的事务中运行(这与jOOQ无关)。对于每个查询,jOOQ总是尝试acquire()
和release()
连接,当这种情况发生在事务上下文之外时,那么连接将被有效关闭(例如返回到连接池)。您应该切换启动事务和运行jOOQ查询的顺序:
// start transaction
// run jOOQ query
// iterate jOOQ results
// run updates
// commit transaction
如果你正在使用声明性事务(例如Spring的@Transactional
注释),那么你就不太可能遇到这个问题,因为你的初始jOOQ查询更有可能已经在同一个事务中了。
为什么附加工作
当您显式地将RelationRecord
附加到配置上时,您将会将一条附加到先前关闭的连接上的记录附加到具有事务连接的新配置上。我假设你的jooq()
方法产生一个新的DSLContext
实例,它包装了当前活动的DataSource
或Connection
。
切换到批量更新
然而,如果你的例子是所有有你的实际逻辑(即你没有简化它为这个堆栈溢出问题),那么为什么不只是运行一个批量更新?这会更简单,更快捷。
jooq()
.update(RELATION)
.set(RELATION.ORGANIZATION_NAME, "OrganizationName")
.where(RELATION.ID.in(
select(BULK_CONTACT_EDIT_CONTACTS.CONTACT_ID)
.from(BULK_CONTACT_EDIT_CONTACTS)
.where(BULK_CONTACT_EDIT_CONTACTS.BULK_CONTACT_EDIT_ID.eq(bulkContactEditId))
.and(BULK_CONTACT_EDIT_CONTACTS.PROCESSED.isFalse())
))
// Since you're using MySQL, you have native UPDATE .. LIMIT support
.limit(batchSize)
.execute();
我假设你的实际例子有点复杂,因为你需要在某个地方设置PROCESSED
标志为true,但是记住这个选项总是好的。