生成内存数据库的事务ID

| 在撰写本文时,TRANSACTION_ID()不支持内存数据库。我可以使用序列表生成自己的ID,但尚不清楚如何将现有ID与触发器进行通信。第一个触发器应生成一个新的ID。后续触发器(在同一事务中)应共享现有ID。 我可以使用线程局部变量来共享现有的ID,但这似乎很脆弱。有一个更好的方法吗?     
已邀请:
        使用序列而不是事务ID呢?
CREATE SEQUENCE SEQ;
事务中的第一个操作设置会话变量,如下所示:
SET @TID = SEQ.NEXTVAL;
该事务中的其他操作使用会话变量:
CALL @TID;
    
        我发现了(非常hacky)解决方法:
/**
 * Invoked when a transaction completes.
 */
public abstract class TransactionListener extends Value
{
    private boolean invoked;

    /**
     * Invoked when the transaction completes.
     */
    protected abstract void onCompleted();

    @Override
    public String getSQL()
    {
        return null;
    }

    @Override
    public int getType()
    {
        throw new AssertionError(\"Unexpected method invocation\");
    }

    @Override
    public long getPrecision()
    {
        throw new AssertionError(\"Unexpected method invocation\");
    }

    @Override
    public int getDisplaySize()
    {
        throw new AssertionError(\"Unexpected method invocation\");
    }

    @Override
    public String getString()
    {
        throw new AssertionError(\"Unexpected method invocation\");
    }

    @Override
    public Object getObject()
    {
        throw new AssertionError(\"Unexpected method invocation\");
    }

    @Override
    public void set(PreparedStatement prep, int parameterIndex) throws SQLException
    {
        throw new AssertionError(\"Unexpected method invocation\");
    }

    @Override
    protected int compareSecure(Value v, CompareMode mode)
    {
        throw new AssertionError(\"Unexpected method invocation\");
    }

    @Override
    public int hashCode()
    {
        throw new AssertionError(\"Unexpected method invocation\");
    }

    @Override
    public boolean equals(Object other)
    {
        throw new AssertionError(\"Unexpected method invocation\");
    }

    @Override
    public boolean isLinked()
    {
        return !invoked;
    }

    @Override
    public void close()
    {
        invoked = true;
        onCompleted();
    }
}

// -------------TRIGGER BELOW-----------

public void fire(final Connection connection, ResultSet oldRow, ResultSet newRow)
    throws SQLException
{
    Statement statement = connection.createStatement();
    long transactionId;
    ResultSet rs = statement.executeQuery(\"SELECT @TRANSACTION_ID\");
    try
    {
        rs.next();
        transactionId = rs.getLong(1);
        if (transactionId == 0)
        {
            // Generate a new transaction id
            rs.close();
            JdbcConnection jdbcConnection = (JdbcConnection) connection;
            final Session session = (Session) jdbcConnection.getSession();
            session.unlinkAtCommit(new TransactionListener()
            {
                @Override
                protected void onCompleted()
                {
                    boolean oldAutoCommit = session.getAutoCommit();
                    session.setAutoCommit(false);
                    try
                    {
                        Statement statement = connection.createStatement();
                        statement.executeQuery(\"SELECT SET(@TRANSACTION_ID, NULL)\");
                        statement.close();
                    }
                    catch (SQLException e)
                    {
                        throw new AssertionError(e);
                    }
                    finally
                    {
                        session.setAutoCommit(oldAutoCommit);
                    }
                }
            });
            rs = statement.executeQuery(\"SELECT SET(@TRANSACTION_ID, \"
                + \"audit_transaction_sequence.NEXTVAL)\");
            rs.next();
            transactionId = rs.getLong(1);
        }
    }
    finally
    {
        rs.close();
    }
    assert (transactionId != 0);
    // ...
}
运作方式如下: 我们使用Session.unlinkAtCommit()来监听事务提交(我也认为这也会引起回滚,但我尚未对此进行验证) 由于我们无法预测触发器调用的数量和顺序,因此必须在每个触发器中进行以下检查: 如果
@TRANSACTION_ID
为null,则注册一个新的事件侦听器并递增顺序。 如果
@TRANSACTION_ID
不为空,则从中获取当前的交易ID。 此解决方法的两个主要问题是: 它非常脆弱。如果Session.unlinkAtCommit()将来更改,则可能会中断事件侦听器。 为了检索交易ID,我们必须在每个触发器的顶部重复很多样板代码。 将其实现为内置函数TRANSACTION_LOCAL_ID()会容易得多。此功能将返回类似于HSQLDB的特定于数据库实例的事务ID。     

要回复问题请先登录注册