在@Async任务中保存资源的正确方法是什么?

时间:2013-12-27 01:02:10

标签: spring java-ee asynchronous

我正在尝试更新异步线程内的资源,该资源重复其任务直到被取消。我使用Future将线程存储在一个hashmap中,以便以后可以取消它。线程按预期分叉,并且Async方法中的对象实例更改其值,但是当我尝试提交它们时,更改不会反映在数据库中,我在控制台上看不到任何错误消息。我已经尝试过@Async和@Transactional的许多不同组合,但仍然没有得到它。我究竟做错了什么?在此先感谢您的帮助!

RoomService.java

@Service
@Transactional
public class RoomService {

@Inject private FooService fooService;
...

public Future<String> startRoom(Room room) {
    Future<String> future = fooService.startFoo(room.getId());
    map.put(room.getId(), future);
    return future;
}

FooService.java

@Service
@Transactional
public class FooService {

...

public void save(Foo foo) {
    getSession().saveOrUpdate(foo);
}

@Async
public Future<String> startFoo(int id) {
    Foo foo = getFooById(id);
    try {
        while (true) {
            foo.setName("Peter");
            save(foo);
            Thread.sleep(10000);
        }
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
    return new AsyncResult<String>("done");
}

1 个答案:

答案 0 :(得分:1)

@Async方法成为@Transactional bean的一部分意味着Spring会截获您的方法两次:一次用于@Transactional将方法包装在Transaction中,一次用于{ {1}}在单独的@Async中执行该方法。

由于proxying works的方式,一旦你进入Thread的方法,就会调用 另一种方法是在实际对象上完成,而不是在具有所有FooService行为的代理上完成。因此,不会创建/提交/回滚新事务。实际的@Transactional边界是Transaction方法本身。但是,由于您的方法执行无限循环,因此该提交永远不会发生。

我建议您在另一个类中创建@Async方法,并为其创建一个bean并注入@Async。这样,FooService行为将实际调用包装到

@Transactional

因此在每次调用时都会提交。