首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Spring事务隔离无效

Spring事务隔离无效
EN

Stack Overflow用户
提问于 2014-02-09 04:05:35
回答 1查看 1.8K关注 0票数 2

我正在做一个非常简单的例子来测试Spring隔离。我有两个非常相似的课程表类:

代码语言:javascript
复制
@Service("manager1")
public class Manager1 {

    private Service1 service1;

    @Scheduled(fixedDelay = 15000)
    public void sendScheduledCampaigns() {
        service1.changeCredits();
    }
...

@Service("manager2")
public class Manager2 {

    private Service2 service2;

    @Scheduled(fixedDelay = 15000)
    public void sendScheduledCampaigns() {
        service2.changeCredits();
    }
...

另外,我还有两个非常相似的服务类:

代码语言:javascript
复制
@Service("service1")
@Transactional
public class Service1 {

    private UserService userService;

    private static Logger log = Logger.getLogger(Service1.class);

    public void changeCredits() {       
        User user = userService.getUserById(1);

        log.info("Service1 previous credits: " + user.getCredits());
        int newCredit = user.getCredits() + 5;
        user.setCredits(newCredit);

        log.info("Service1 new credits: " + user.getCredits());
    }
...

@Service("service2")
@Transactional
public class Service2 {

    private UserService userService;

    private static Logger log = Logger.getLogger(Service2.class);

    public void changeCredits() {

         User user = userService.getUserById(1);

        log.info("Service2 previous credits: " + user.getCredits());
        int newCredit = user.getCredits() + 5;
        user.setCredits(newCredit);

        log.info("Service2 new credits: " + user.getCredits());
    }

在运行这段代码之后,我可以看到,当两个事务同时执行时,两个事务从数据库中获得相同的值。因此,他们忽视了另一种方法的修改。我认为这是事务隔离中的一个错误:

代码语言:javascript
复制
INFO  27 Feb 2014 14:14:22 - Service1 previous credits: 0
INFO  27 Feb 2014 14:14:22 - Service2 previous credits: 0
INFO  27 Feb 2014 14:14:22 - Service1 new credits: 5
INFO  27 Feb 2014 14:14:22 - Service2 new credits: 5

这里的信用值应该是10

在此之后,由于两个进程没有同时执行,计算开始正常:

代码语言:javascript
复制
Feb 27, 2014 2:14:23 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-bio-8080"]
Feb 27, 2014 2:14:23 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["ajp-bio-8009"]
Feb 27, 2014 2:14:23 PM org.apache.catalina.startup.Catalina start
INFO: Server startup in 10698 ms
INFO  27 Feb 2014 14:14:37 - Service2 previous credits: 5
INFO  27 Feb 2014 14:14:37 - Service2 new credits: 10
INFO  27 Feb 2014 14:14:38 - Service1 previous credits: 10
INFO  27 Feb 2014 14:14:38 - Service1 new credits: 15

我正在使用MYSQL,这些是我的任务和事务配置:

代码语言:javascript
复制
<task:annotation-driven executor="myExecutor" scheduler="myScheduler"/>
<task:executor id="myExecutor" pool-size="100"/>
<task:scheduler id="myScheduler" pool-size="100"/>

<tx:annotation-driven transaction-manager="transactionManager"/>

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

<bean id="sessionFactory"
    class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="dataSource" ref="myDataSource" />
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop>
            <prop key="hibernate.show_sql">false</prop>
        </props>
    </property>
    <property name="packagesToScan" value="test.domain" />
</bean>

由于某些原因,我的默认隔离级别是。我是从这个得到的:

代码语言:javascript
复制
log.info("isolation: " +TransactionSynchronizationManager.getCurrentTransactionIsolationLevel()); 

因此,我试图更改这两个服务的隔离级别:

代码语言:javascript
复制
@Service("service1")
@Transactional(isolation=Isolation.REPEATABLE_READ)
public class Service1 {

@Service("service2")
@Transactional(isolation=Isolation.REPEATABLE_READ)
public class Service2 {

结果仍然是错误的。

你知道为什么会发生这种事吗?

提前谢谢。

EN

回答 1

Stack Overflow用户

发布于 2014-02-09 04:21:22

在本例中,@Transaction使用默认隔离(这取决于所使用的数据库),请尝试使用隔离属性和Isolation.REPEATABLE_READ来获取所需的行为。

表示事务隔离级别的Enum(隔离)枚举,用于与事务注释(对应于TransactionDefinition接口)一起使用。

http://docs.spring.io/spring/docs/3.2.x/javadoc-api/org/springframework/transaction/annotation/Isolation.html#DEFAULT

当允许事务从已被另一个正在运行的事务修改但尚未提交的行读取数据时,就会发生脏读。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21655113

复制
相关文章

相似问题

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