首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Spring中设置快照隔离级别

如何在Spring中设置快照隔离级别
EN

Stack Overflow用户
提问于 2015-06-23 22:05:21
回答 1查看 2.5K关注 0票数 1

有人能帮助我理解如何在Spring中将隔离级别设置为SNAPSHOT吗?

我接管了一个以前由其他人开发的项目,在某些情况下,我们在使用数据库时会陷入死锁。我已经验证过,尽管有SNAPSHOT的DB隔离级别,但当应用程序发出请求时,该事务的隔离级别将更改为READ_COMMITTED。根据我的简短研究,如果没有显式设置,hibernate使用DEFAULT隔离,SQLServer 2012的隔离是READ_COMMITTED

不幸的是,无论是Spring还是Hibernate,我都不是专家,所以我只提供一些似乎相关的信息:

代码语言:javascript
复制
<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的每个实例上设置隔离级别。这些吐露变成了这样:

代码语言:javascript
复制
<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,我认为它是DEFAULTREAD_UNCOMMITTEDREAD_COMMITTEDREPEATABLE_READSERIALIZABLE

是否有一种经过验证的方法可以在我所拥有的信任的上下文中将隔离级别设置为SNAPSHOT (或4096)?

谢谢。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-06-24 05:40:04

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

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

代码语言:javascript
复制
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来代替:

代码语言:javascript
复制
<bean class="my.package.CustomIsolationLevelDataSourceAdapter">
    <constructor-arg value="4096"/>
</bean>
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31014345

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档