3

We are refactoring a legacy application. The old code did something like this in a Controller method:

  • Call DAO1.update()
  • Call DAO2.update()

We’ve placed an in between a service layer, so the above code now looks like:

  • Call Service1.update() --> Call DAO1.update()
  • Call Service2.update() --> Call DAO2.update()

Each of the above two update methods have been marked transactional (using spring transactions). Old code didn’t handle transactions that well – now, we want a user action (controller method) to map only to a single transaction. How can we achieve that using spring transactions itself?

PS:

  1. We did checked Hibernate’s Open Session in View pattern, but we would like a solution that makes use of Spring transactions – the above scenarios are not that common and we are worried about performance decay in OSIV pattern.
  2. We can combine the two service methods above into a single method but would welcome a bit cleaner situation that won’t hinder reuse.
matt b
  • 138,234
  • 66
  • 282
  • 345
haps10
  • 3,496
  • 6
  • 32
  • 38

2 Answers2

4

We can combine the two service methods above into a single method but would welcome a bit cleaner situation that won’t hinder reuse.

IMHO if you are attempting to execute these two service methods as one "unit of work", then the cleanest solution is to have both of them called in a @Transactional method in the service layer.

matt b
  • 138,234
  • 66
  • 282
  • 345
3

If you want to keep using the @Transactional annotation, then you sure have to wrap your calls in a broader, annotated method. So, either you define business services, which may become quite boilerplate/redundant indeed, or you make your controller's handling method transactional itself (as a @Component it is a Spring-managed bean so you can use @Transactional there too), or you define a flexible, generic, callback-based template:

@Component
public class TxWorker {
    @Transactional
    public <T> T doInTx(Callable<T> callback) throws Exception {
        return callback.call();
    }
}

The drawback of the latter is that it may become a bit messy if you overuse it.

Note that you may combine the OpenSessionInView pattern and Spring-managed transactions, since the Hibernate session (or JPA entityManager) may span across many tx (see What is the difference between Transaction-scoped Persistence context and Extended Persistence context?). But its main goal is to provide lazy-loading while rendering views, so it is not exactly what you're looking for.

Community
  • 1
  • 1
Vincent
  • 1,035
  • 6
  • 14