我正在使用postgresql 9.2和C3p0 0.9.2.1,我创建了一个连接定制器来禁用autoCommit
并设置transactionMode
,但是当我在InitialContext
上查找以检索dataSource
时,autoCommit
不会在连接上被禁用(日志在底部)。如何禁用自动提交?
连接自定义程序:
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);
}
}
类检索DAOs的数据源:
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 auto commit mode is disabled那么为什么c3p0会自动激活它呢?是否应将forceignoreunolvedtransactions设置为true?
编辑:每当我在检索数据源后提交事务时,都会出现以下错误:
org.postgresql.util.PSQLException: Cannot commit when autoCommit is enabled.
最佳答案
JDBC spec声明,“默认值是在创建连接对象时启用自动提交模式。”这是跨DBMS的默认值,无论数据库在其他上下文中的行为如何。JDBC程序员可能依赖于设置自动提交,除非他们显式调用setAutoCommit( false )
。c3p0以此为荣。
c3p0允许connectioncustomizer在未指定单个行为时持久重写onAcquire()
方法中的连接默认值。例如,规范声明“连接对象的默认事务级别由驱动程序决定
因此,对于transactionIsolation,如果您在onAcquire(...)
中重置它,c3p0将记住您选择的默认值,并始终在签出之前将transactionIsolation恢复到该默认值。但是,c3p0显式不允许您在autoCommit
中禁用onAcquire(...)
,并且在默认情况下禁用autoCommit
。在退房的时候,c3p0坚持你有一个符合规范的连接。
您可以通过重写onCheckOut(...)
方法来获得所需的行为。当调用onCheckOut(...)
时,连接已经被签出,您可以在那里做任何您想做的事情,c3p0已经用尽了它对规范神的义务。如果希望客户端始终看到非自动提交连接,请在setAutoCommit( false )
中调用onCheckOut(...)
。但请注意,这会使您的客户端代码不可移植。如果您离开c3p0并切换到另一个数据源,则需要使用一些其他特定于库的方法来始终禁用autoCommit
,否则您会发现您的应用程序行为不当。因为即使对于postgres,默认情况下JDBC连接也是autoCommit
。
注意:连接属性的值不是由规范固定的,因此可以在onAcquire(...)
方法中持久重写,这些属性是catalog
、holdability
、transactionIsolation
、readOnly
和typeMap
。
p.s.不要将forceIgnoreUnresolvedTransactions
设置为true
。大笑。