Reputation: 4146
I'm using a UnitOfWork
in a background task method (operated by Quartz) with Guice-persist on top of hibernate. The background task call a service, which need to commit the current transaction in the middle of it's task - and continue on another transaction. How can I commit the current UnitOfWork and create a new one?
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();
} }
The service is also managed by Guice, but is a singleton, and do not have access to the caller UnitOfWork
as is.
Ideally I do not want to change service signature. A workaround is for the caller to give two UnitOfWork
as parameters to foo()
, but this seems a bit hacked.
EDIT: For ease of use of future fellow reader, here is my implementation of the solution given by ColinD, which fits the bill nicely:
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() { ... }
}
Upvotes: 1
Views: 2299
Reputation: 11487
This may fit the bill.
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();
}
}
}
Upvotes: 0
Reputation: 110054
If I recall correctly, a unit of work in Guice Persist is not a single transaction. Rather, it represents a single unit of work such as a single web request or, in your case, a single background job. I believe that a single database connection is used for a whole unit of work, but that unit of work may have multiple distinct transactions. In fact, I think that just starting and ending a unit of work will not cause any transactions to be started or ended.
I think what you want to do is to annotate both foo1()
and foo2()
(but not foo()
) with @Transactional
. As long as there's no outer transaction wrapping both calls, they'll each run in a separate transaction.
Upvotes: 4