connection.close() 上的事务仍然存在时无法关闭连接

Cannot close a connection while a transaction is still alive Exception on connection.close()

我有一个方法可以创建与嵌入式 Derby 数据库的连接并对其执行 Select 查询。

public PersonMID findPersonMID(String personAlias, CodeUID aliasTypeCodeUID, LogicalDomainMID logicalDomainMID) throws SQLException
{
    Connection connection = getConnection();

    try
    {
        QueryExecutor<Long> findPersonIdByPersonAliasExecutor = FindPersonIdByPersonAliasDelegate.getExecutor(authority,connection, personAlias);

        Long result = findPersonIdByPersonAliasExecutor.execute();

        if(result == null)
        {
            return null;
        }
        return PersonMID.create(authority, result);
    }
    finally
    {
        JDBCAssistant.close(connection);
    }

这是我的查询:

select P.PRSON_ID from PRSON_ALIAS PA join PRSON P on P.PRSON_ID = PA.PRSON_ID and P.LOGICAL_DOMAIN_ID = ? where PA.PRSON_ALIAS_TYPE_CD = ? and    PA.ALIAS = ?

当我 运行 通过这段代码时,我得到一个异常 JDBCException: java.sql.SQLException: Cannot close a connection while a transaction is still active.

但是当我在关闭 Connection 或设置 autoCommit true 之前调用 Connection.commit() 时(默认情况下它设置为 false Connection) 对于我的 Connection,它允许我成功关闭连接并获得所需的结果。

但是我真的需要为 Select 操作调用 commit() 吗?有什么可犯的?如果我不提交,是否有某个地方没有被释放的锁?

这个 post 说我不应该这样做。我应该能够关闭连接而无需提交或回滚。

我错过了什么?

如果您 不是 autoCommit 模式,那么 SELECT 语句实际上持有读锁,具体取决于您的隔离级别,等等提交 SELECT 查询不仅仅是空操作。

是的,数据库没有变化,但是提交仍然告诉数据库引擎你的事务已经完成了对数据的查看,因此它可以允许其他事务修改数据。

这是一些背景知识 material:

  1. 隔离级别和并发; https://db.apache.org/derby/docs/10.12/devguide/cdevconcepts15366.html
  2. 共享锁:https://db.apache.org/derby/docs/10.12/devguide/cdevconcepts842304.html