1

我正在使用UnitOfWorkGuice-persist 在休眠之上的后台任务方法(由 Quartz 操作)。后台任务调用一个服务,该服务需要在其任务中间提交当前事务 - 并继续另一个事务。如何提交当前的 UnitOfWork 并创建一个新的?

class BackgroundJob {
    @Inject UnitOfWork unitOfWork;
    @Inject MyService myService;
    public void run() {
        try {
            unitOfWork.begin();
            myService.foo();
        } finally {
            unitOfWork.end();
}   }   }

class MyServiceImpl implements MyService {
    @Override public void foo() {
        foo1();
        // I would like to commit here and start a new transaction
        foo2();
}   }

该服务也由 Guice 管理,但它是一个单例,并且无法按原样访问调用UnitOfWork

理想情况下,我不想更改服务签名。一种解决方法是让调用者将两个UnitOfWork作为参数提供给foo(),但这似乎有点被黑了。

编辑:为了方便未来的读者使用,这是我对 ColinD 给出的解决方案的实现,它非常符合要求:

class BackgroundJob {
    @Inject UnitOfWork unitOfWork;
    @Inject MyService myService;
    public void run() {
        try {
            unitOfWork.begin();
            myService.foo();
        } finally {
            unitOfWork.end();
}   }   }

class MyServiceImpl implements MyService {
    @Override public void foo() {
        foo1();
        foo2();
    }
    @Transactional private void foo1() { ... }
    @Transactional private void foo2() { ... }
}
4

2 回答 2

4

如果我没记错的话,Guice Persist 中的一个工作单元不是单个事务。相反,它代表单个工作单元,例如单个 Web 请求,或者在您的情况下,代表单个后台作业。我相信单个数据库连接用于整个工作单元,但该工作单元可能有多个不同的事务。事实上,我认为仅仅开始和结束一个工作单元不会导致任何事务的开始或结束。

我认为你想要做的foo1()是用. 只要没有包装这两个调用的外部事务,它们就会各自在单独的事务中运行。foo2()foo()@Transactional

于 2012-02-09T14:59:05.830 回答
0

这可能符合要求。

class BackgroundJob {
    @Inject UnitOfWork unitOfWork;
    @Inject MyService myService;

    public void run() {
        try {
            unitOfWork.begin();
            myService.foo1();
            unitOfWork.end();
           unitOfWork.begin();
            myService.foo2();
            unitOfWork.end();
        } finally {
            unitOfWork.end();
        }
    }
}
于 2012-02-08T18:08:42.567 回答