如何在Spring中设置SNAPSHOT隔离级别

时间:2015-06-23 22:05:21

标签: java sql-server spring hibernate isolation-level

有人可以帮我理解如何在Spring的XML配置中将隔离级别设置为temp吗?

我正在接管一个曾经由别人开发的项目,在某些情况下,我们在使用数据库时会遇到死锁。我已经验证,尽管数据库隔离级别为SNAPSHOT,但当应用程序发出请求时,该事务的隔离级别将更改为SNAPSHOT。根据我的简短研究,如果没有明确设置,hibernate使用READ_COMMITTED隔离,对于SQLServer 2012是DEFAULT

不幸的是,我不是Spring或Hibernate的专家,所以我只是给出看似相关的配置:

READ_COMMITTED

在研究可能的解决方案时,我还了解到,在提供<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName"> <value>jdbc/ds</value> </property> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="mappingResources"> <list> ... </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">${nn.hibernate.dialect}</prop> <prop key="hibernate.show_sql">${nn.hibernate.showSQL}</prop> <prop key="hibernate.generate_statistics">${nn.hibernate.generatestatics}</prop> <prop key="hibernate.hbm2ddl.auto">${nn.hibernate.hbm2ddl}</prop> <prop key="hibernate.jdbc.batch_size">${nn.hibernate.batchsize}</prop> <prop key="hibernate.cache.provider_class">${nn.hibernate.cache.provider_class}</prop> <prop key="hibernate.cache.use_second_level_cache">${nn.hibernate.cache.use_second_level_cache}</prop> </props> </property> </bean> <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory"> <ref local="sessionFactory" /> </property> </bean> <tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="save*" read-only="false" rollback-for="NNDBException"/> <tx:method name="update*" read-only="false" rollback-for="NNDBException"/> <tx:method name="checkFor*" read-only="false" rollback-for="NNDBException"/> <tx:method name="*"/> </tx:attributes> </tx:advice> <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate"> <property name="sessionFactory" ref="sessionFactory" /> </bean> 时设置hibernate.connection.isolation无效。

从那里我到this example,其中DataSource用于在IsolationLevelDataSourceAdapter的每个实例上设置隔离级别。配置变成了这个:

Connection

我在<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName"> <value>jdbc/ds</value> </property> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource"> <bean class="org.springframework.jdbc.datasource.IsolationLevelDataSourceAdapter"> <property name="targetDataSource" ref="dataSource"/> <property name="isolationLevel" value="4096" /> </bean> </property> <property name="mappingResources"> <list> ... </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">${nn.hibernate.dialect}</prop> <prop key="hibernate.show_sql">${nn.hibernate.showSQL}</prop> <prop key="hibernate.generate_statistics">${nn.hibernate.generatestatics}</prop> <prop key="hibernate.hbm2ddl.auto">${nn.hibernate.hbm2ddl}</prop> <prop key="hibernate.jdbc.batch_size">${nn.hibernate.batchsize}</prop> <prop key="hibernate.cache.provider_class">${nn.hibernate.cache.provider_class}</prop> <prop key="hibernate.cache.use_second_level_cache">${nn.hibernate.cache.use_second_level_cache}</prop> </props> </property> </bean> <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory"> <ref local="sessionFactory" /> </property> <property name="allowCustomIsolationLevels" value="true" /> </bean> <tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="save*" read-only="false" rollback-for="NNDBException"/> <tx:method name="update*" read-only="false" rollback-for="NNDBException"/> <tx:method name="checkFor*" read-only="false" rollback-for="NNDBException"/> <tx:method name="*"/> </tx:attributes> </tx:advice> <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate"> <property name="sessionFactory" ref="sessionFactory" /> </bean> 中将隔离级别设置为4096。但是,这就是我碰到的地方:sessionFactory,我认为它是IllegalArgumentException: Only isolation constants allowedDEFAULTREAD_UNCOMMITTEDREAD_COMMITTEDREPEATABLE_READ

在我的配置环境中,是否有一种经过验证的方法可以将隔离级别设置为SERIALIZABLE(或SNAPSHOT)?

谢谢。

1 个答案:

答案 0 :(得分:3)

IsolationLevelDataSourceAdapter检查标准隔离级别代码,这是一个明显的限制(我建议您为此提交一个Spring JIRA问题)。

要解决此问题,您需要扩展IsolationLevelDataSourceAdapter类:

public class CustomIsolationLevelDataSourceAdapter extends IsolationLevelDataSourceAdapter {

    private final Integer customIsolationLevel;

    public CustomIsolationLevelDataSourceAdapter(Integer customIsolationLevel) {
        this.customIsolationLevel = customIsolationLevel;
    }

    @Override
    protected Integer getIsolationLevel() {
        return customIsolationLevel != null ? customIsolationLevel : super.getIsolationLevel();
    }
}

并改为使用此dataSource

<bean class="my.package.CustomIsolationLevelDataSourceAdapter">
    <constructor-arg value="4096"/>
</bean>