在Tomcat 6上禁用Oracle UCP的自动提交



我在Tomcat 6上使用Hibernate 3.3.2和Spring 3.2.3。我想使用一个连接池,并决定测试Oracle的UCP(适用于Oracle 11.2.0.4)

(我在这篇文章的末尾添加了编辑,因为经过一些发展,情况发生了变化)

不过我无法摆脱自动提交。我尝试在Tomcat的context.xml:中这样配置数据源

    <Resource
    name="jdbc/datasource"
    auth="Container"
    type="oracle.ucp.jdbc.PoolDataSource"
    [snip]
    initialPoolSize="3"
    minPoolSize="3"
    maxPoolSize="10"
    factory="oracle.ucp.jdbc.PoolDataSourceImpl"
    connectionFactoryClassName="oracle.jdbc.pool.OracleDataSource"
    connectionProperties=";AutoCommit=false;"
/>

注意分号。我添加它们是因为这个帖子。但无论是使用分号还是不使用分号,它都不起作用。

在我的应用程序中,我有一些测试代码如下:

        PoolDataSourceImpl pds;
    try {
        pds = (PoolDataSourceImpl) hc.dataSource();
        System.out.println("Print all conn props:" + pds.getConnectionProperties().toString());
    } catch (NamingException e) {
        e.printStackTrace();
    }
    sessionFactory.getCurrentSession().doWork(new Work() {
        @Override
        public void execute(Connection connection) throws SQLException {
            System.err.println("################################### autocommit is " + connection.getAutoCommit());
        }
    });

输出为:

Print all conn props:{AutoCommit=false}
################################### autocommit is true

我还试着用Hibernate.connection.autocommit=false禁用Hibernate中的自动提交,但这也不起作用。

编辑:我的配置如下:

@Configuration
public class HibernateConfig {
@Bean
LocalSessionFactoryBean hibernateSessionFactory() throws Exception {
    LocalSessionFactoryBean factory = new LocalSessionFactoryBean();
    factory.setMappingResources(new String[] { "mapping.hbm.xml" });
    factory.setHibernateProperties(hibernateProperties());
    factory.setDataSource(dataSource());
    return factory;
}
@Bean
public DataSource dataSource() throws NamingException {
    return (DataSource) new InitialContext().lookup("jdbc/datasource");
}
@Bean
public HibernateTransactionManager transactionManager() throws Exception {
    HibernateTransactionManager manager = new HibernateTransactionManager();
    manager.setSessionFactory(hibernateSessionFactory().getObject());
    return manager;
}
@Bean
Properties hibernateProperties() throws IOException {
    PropertiesFactoryBean bean = new PropertiesFactoryBean();
    bean.setLocation(new ClassPathResource("hibernate.properties"));
    bean.afterPropertiesSet();
    return bean.getObject();
}

@Configuration
@EnableTransactionManagement
@EnableScheduling
@Import({ HibernateConfig.class, ... })
@ComponentScan(basePackages = ...)
public class ServerCommonsConfig {
    [...]
}

@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
@Import({ ServerCommonsConfig.class, ... })
public class ApplicationServerConfig {
    [...]
}

hibernate.properties如下所示:

# Hibernate Properties
#hibernate.bytecode.provider=cglib
hibernate.dialect=org.hibernate.dialect.Oracle10gDialect
hibernate.show_sql=true
hibernate.format_sql=true
hibernate.cache.provider_class=org.hibernate.cache.NoCacheProvider
hibernate.cache.use_second_level_cache=false
hibernate.cache.use_query_cache=false
hibernate.jdbc.batch_size=200
hibernate.connection.autocommit=false
connection.autocommit=false

第2版:

显然,autoCommit属性的名称有一个拼写错误。必须是

connectionProperties=";autoCommit=false;"

开头带有一个小"a"。我使用了大写版本,因为我在仅有的一个在网络上关闭autoCommit的情况下配置UCP的例子中发现了这一点。

现在测试输出为

Print all conn props:{autoCommit=false}
false
################################### autocommit ist false

一切都很美好,但现在什么都没做。我看到Hibernate在刷新时编写DELETE语句,在@Transactional方法结束后,我可以调试到Spring的TransactionAspectSupport和Hibernate TransactionManager.doCommit(),最后是JDBCTransaction.commitAndResetAutoCommit(

private void commitAndResetAutoCommit() throws SQLException {
    try {
        jdbcContext.connection().commit();
    }
    finally {
        toggleAutoCommit();
    }
}

,但数据库对此并不担心。未提交任何更改。

数据访问代码示例(这是客户端通过Spring HTTP调用程序调用的服务器上的服务):

@Transactional
@Component
public class ServiceImpl implements Service {
    @Resource
    private SessionFactory sessionFactory;
    //added this method to test the autocommit issue
    @Override
    public List<Stuff> getStuff(Long id) {
        Query query = sessionFactory.getCurrentSession().createQuery(
                "FROM Stuff p");
        @SuppressWarnings("unchecked")
        List<Stuff> list = query.list();
        for (Stuff stuff : list) {
            sessionFactory.getCurrentSession().delete(stuff);
        }
        //this flush used to commit the changes
        //instead, now nothing gets committed
        sessionFactory.getCurrentSession().flush();
        return null;
    }
}

Spring自动为您管理连接(假设您使用Spring控制的事务和Spring配置中的数据源)。因此,您不需要对连接的只读设置进行繁琐的处理。

此外,如果您使用spring将数据源注入hibernate,那么hibernate.connection.*属性将毫无用处。

相关内容

  • 没有找到相关文章

最新更新