有人能帮助我理解如何在Spring中将隔离级别设置为SNAPSHOT吗?
我接管了一个以前由其他人开发的项目,在某些情况下,我们在使用数据库时会陷入死锁。我已经验证过,尽管有SNAPSHOT的DB隔离级别,但当应用程序发出请求时,该事务的隔离级别将更改为READ_COMMITTED。根据我的简短研究,如果没有显式设置,hibernate使用DEFAULT隔离,SQLServer 2012的隔离是READ_COMMITTED。
不幸的是,无论是Spring还是Hibernate,我都不是专家,所以我只提供一些似乎相关的信息:
<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时设置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>在sessionFactory中,我将隔离级别设置为sessionFactory。然而,这正是我碰壁的地方:IllegalArgumentException: Only isolation constants allowed,我认为它是DEFAULT、READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ和SERIALIZABLE。
是否有一种经过验证的方法可以在我所拥有的信任的上下文中将隔离级别设置为SNAPSHOT (或4096)?
谢谢。
发布于 2015-06-24 05:40:04
IsolationLevelDataSourceAdapter检查标准隔离级别代码,这是一个明显的限制(我建议您为此提交一个Spring问题)。
要解决这个问题,您需要扩展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>https://stackoverflow.com/questions/31014345
复制相似问题