有人可以帮我理解如何在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 allowed
,DEFAULT
,READ_UNCOMMITTED
,READ_COMMITTED
和REPEATABLE_READ
在我的配置环境中,是否有一种经过验证的方法可以将隔离级别设置为SERIALIZABLE
(或SNAPSHOT
)?
谢谢。
答案 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>