9

I am developing a project with spring framework. I have following architecture: all database code is in dao classes, all application logic is in service classes, http requests are processed using spring mvc rest controllers.

@Repository
public class UserDao {

    @PersistenceContext
    private EntityManager em;

    public void editUser(User user) {
        ...
    }
}

@Service
public class UserService {

    @Autowired
    private UserDao userDao;

    @Transactional
    public void editUser(User user) {
        ...
    }
}

@RestController
@RequestMapping(value = "/UserCtrl", produces = "application/json;charset=UTF-8")
public class UserCtrl {

    private static final Logger logger = LogManager.getLogger(AppConfig.LOGGER_NAME);

    @Autowired
    private ApplicationContext appContext;

    @RequestMapping(value = "/editUser")
    public ActionResult editUser(@ModelAttribute User user) {
        ActionResult rslt = new ActionResult();

        try {
            UserService userService = appContext.getBean(UserService.class);
            userService.editUser(user);

            rslt.setSuccess(true);
        } catch (Exception ex) {
            logger.error("editUser", ex);
            rslt.setSuccess(false);
        }

        return rslt;
    }
}

This code works correctly. One thing I cannot understand is how aop proxy of UserService bean starts transaction, when EntityManager is injected only in UserDao class. Can somebody explain me how this works and how EntityManager lifecycle is managed by spring framework ?

Any help appreciated.

Yoh0xFF
  • 1,450
  • 2
  • 18
  • 31

2 Answers2

18

The TransactionManager is responsible for managing the transaction boundaries in Spring Framework. When you annotate the business method with @Transactional you are instrumenting the method with an aspect. Before executing the method, this aspect interact with TransactionManager which decides if it is necessary to create a new Transaction or use a preexisting one. In the case of create a new Transaction, a new Entity Manager is created from EntityManagerFactory and is associated to the current thread alonside with the Transaction.

The EntityManager is responsible to iterate with the database. When you inject it with @PersistenceContext, Spring injects an proxy to the EntityManager. Whenever an operation is executed in the EntityManager proxy it looks the EntityManager associated with the thread.

Marcelo Keiti
  • 1,200
  • 9
  • 10
3

Based on the snippet of code you provide you are using spring with some implementation of JPA you are using J2EE container for your web application and bases on my guess I think this is good article about how things works.

Basic concepts :

  1. EntityManager - A class that manages the persistent state(or lifecycle) of an entity.
  2. Persistence Unit - is a named configuration of entity classes.
  3. Persistence Context - is a managed set of entity instances. The entities classes are part of the Persistence Unit configurations.
  4. Managed Entities - an entity instance is managed if it is part of a persistence context and that Entity Manager can act upon it.

Based on this article you use Container Managed EntityManager by using @PersistenceContext

When a container of the application(be it a Java EE container or any other custom container like Spring) manages the lifecycle of the Entity Manager, the Entity Manager is said to be Container Managed. The most common way of acquiring a Container Managed EntityManager is to use @PersistenceContext annotation on an EntityManager attribute.

And the injection is like this :

A Transaction Scoped Entity Manager is returned whenever a reference created by @PersistenceContext is resolved.

and

Every time an operation is invoked on an Entity Manager, the container proxy(the container creates a proxy around the entity manager while instantiating it ) checks for any existing Persistence Context on the JTA Transaction. If it finds one, the Entity Manager will use this Persistence Context. If it doesnt find one, then it will create a new Persistence Context and associates it with the transaction.

So the lifecycle of of entity manager is managed by your container and

we work with an instance of EntityManager, the only role of EntityManager is to determine the lifetime of the Persistence Context. It plays no role in dictating how a Persistence Context should behave. To reiterate, Persistence Context is a managed set of Entity instances. Whenever a transaction begins, a Persistence Context instance gets associated with it. And when a Transaction ends(commits for example), the Persistence Context is flushed and get disassociated with the transaction.

In the nutshell container instantiate your EntityManager by the EntityManagerFactory you provide and manage it's lifecycle but inject the proxy of EntityManager for you. The TransactionManager is responsible for creating, commiting and ... tranactions based on annotations you provide ,whenever it begins the transaction the PersistancecContext associated with it and when the tranasction ends it commites the state of PersistenceContext. The EntityManager works with PersistenceContext and if it's not provided the EntityManager creates one. The EntityManager is threadsafe as long as it holds no state and the state (PersistenceContext) is attached to current tranasction.

Hope this helps.