Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring transactions, EntityManager lifecycle

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.

like image 481
Yoh0xFF Avatar asked Feb 20 '15 01:02

Yoh0xFF


People also ask

How does transaction management work in Spring?

Transactions and Proxies. At a high level, Spring creates proxies for all the classes annotated with @Transactional, either on the class or on any of the methods. The proxy allows the framework to inject transactional logic before and after the running method, mainly for starting and committing the transaction.

Why @transactional annotation is used in Spring?

Annotation Type Transactional. Describes a transaction attribute on an individual method or on a class. When this annotation is declared at the class level, it applies as a default to all methods of the declaring class and its subclasses.

How do you check if @transactional is working?

You can check if transaction is active using TransactionSynchronizationManager. isActualTransactionActive() . But you should call it before a service method executing. TransactionStatus status = TransactionAspectSupport.

What is @transactional in JPA?

The transactional annotation itself defines the scope of a single database transaction. The database transaction happens inside the scope of apersistence context. The persistence context is in JPA the EntityManager , implemented internally using an Hibernate Session (when using Hibernate as the persistence provider).


1 Answers

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.

like image 127
A.R Afsharian Avatar answered Oct 26 '22 14:10

A.R Afsharian