3

我正在使用 postgresql 9.2 和 C3p0 0.9.2.1,我创建了一个连接定制器来禁用autoCommit和设置transactionMode,但是当我进行查找InitialContext以检索 时dataSourceautoCommit连接上并没有禁用(登录底部)。如何禁用自动提交?

连接定制器:

public class IsolationLevelConnectionCustomizer extends
        AbstractConnectionCustomizer {

    @Override
    public void onAcquire(Connection c, String parentDataSourceIdentityToken)
            throws Exception {
        super.onAcquire(c, parentDataSourceIdentityToken);
        System.out.println("Connection acquired, set autocommit off and repeatable read transaction mode.");
        c.setAutoCommit(false);
        c.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
    }
}

为 DAO 检索数据源的类:

public class DAOAcquire {
    private ComboPooledDataSource m_cpdsDataSource = null;
    private static final String LOOKUP_CONNECT = "jdbc/mydb";

    public DAOAcquire() throws NamingException {
        InitialContext context = new InitialContext();
        m_cpdsDataSource = (ComboPooledDataSource) context.lookup(LOOKUP_CONNECT);

        if (m_cpdsDataSource != null) {
            try {
                System.out.println("Autocommit = "+String.valueOf(m_cpdsDataSource.getConnection().getAutoCommit()));

            } catch (SQLException e) {
                System.out.println("Could not get autocommit value : "+e.getMessage());
                e.printStackTrace();
            }
        }
    }

    public ComboPooledDataSource getComboPooledDataSource() {
        return m_cpdsDataSource;
    }

    /**
     * @return the jdbcTemplate
     * @throws NamingException 
     */
    public JdbcTemplate getJdbcTemplate() throws NamingException {
        return new JdbcTemplate(m_cpdsDataSource);
    }

    /**
     * Commit transactions
     * @throws SQLException
     */
    public void commit() throws SQLException {
        if (m_cpdsDataSource != null) {
            m_cpdsDataSource.getConnection().commit();
        } else {
            throw new SQLException("Could not commit. Reason : Unable to connect to database, dataSource is null.");
        }
    }

    /**
     * rollback all transactions to previous save point
     * @throws SQLException
     */
    public void rollback() throws SQLException {
        if (m_cpdsDataSource != null) {
            m_cpdsDataSource.getConnection().rollback();
        } else {
            throw new SQLException("Could not rollback. Reason : Unable to connect to database, dataSource is null.");
        }
    }
}

日志 :

Connection acquired, set autocommit off and repeatable read transaction mode.
Connection acquired, set autocommit off and repeatable read transaction mode.
Connection acquired, set autocommit off and repeatable read transaction mode.
Autocommit = true

默认情况下,postgresql 自动提交模式是禁用的,那么为什么 c3p0 会自动激活它呢?我应该将 forceIgnoreUnresolvedTransactions 设置为 true 吗?

编辑:每当我在检索数据源后提交事务时,都会收到此错误:

org.postgresql.util.PSQLException: Cannot commit when autoCommit is enabled.

4

1 回答 1

7

JDBC 规范指出,“默认设置是在创建 Connection 对象时启用自动提交模式。” 这是一个跨 DBMS 的默认设置,无论数据库在其他上下文中的行为如何。除非明确调用 JDBC 程序员,否则他们可能会依赖设置的 autoCommit setAutoCommit( false )。c3p0 尊重这一点。

onAcquire()当没有指定单一行为时,c3p0 允许 ConnectionCustomizers 持续覆盖方法中的 Connection 默认值。例如,规范声明“连接对象的默认事务级别由提供连接的驱动程序确定”。因此,对于 transactionIsolation,如果您在 中重置它onAcquire(...),c3p0 将记住您选择的默认值,并始终在结帐之前将 transactionIsolation 恢复为该默认值。但是,c3p0 明确不允许您禁用autoCommit一次,onAcquire(...)并且autoCommit默认情况下已禁用。在结帐的那一刻,c3p0 坚持你有一个符合规范的连接。

您可以通过覆盖该onCheckOut(...)方法来获得所需的行为。Connection 在被调用时已经被检出onCheckOut(...),你可以在那里做任何你想做的事情,c3p0 在那时已经用尽了它对规范之神的义务。如果您希望您的客户始终看到非自动提交连接,请调用setAutoCommit( false ). onCheckOut(...)但请注意,这会使您的客户端代码不可移植。如果您离开 c3p0 并切换到不同的 DataSource,您将需要使用其他一些特定于库的方法来始终禁用autoCommit,否则您会发现您的应用程序行为异常。因为即使对于 postgres,JDBC 连接也是autoCommit默认的。

注意:连接属性的值未由规范固定,因此可以在onAcquire(...)方法中永久覆盖,包括catalogholdabilitytransactionIsolationreadOnlytypeMap

ps不要设置forceIgnoreUnresolvedTransactionstrue。玉。

于 2013-07-04T09:06:01.633 回答