简体   繁体   中英

@Transactional Method Calling - should we pass objects as parameters?

@Transactional
public void schoolProcessing{
    //some logic here
    save(student);  //student is now managed
    //Calling update student
     updateStudent(student) or  updateStudent();
    //which of the above is the correct way 
}

public void updateStudent(Student student) {
    //some student update logic
}

While calling methods from @Transactional methods in JPA, should we pass the managed entities as parameters ? Or is it that since this is marked as @Transactional, JPA seamless handles all the persistence as if all the methods being called from @Transactional were within the same method ?

To clarify, would the above piece of code be the same as the below in all respects.

@Transactional
public void schoolProcessing{
    //some logic here
    save(student);  //student is now managed

    //some student update logic
}

I think this is a basic question,but have seen other questions but couldn't get it clarified. Thanks.

The short answer: Both will work

The long answer:

There are a lot of details when it comes to @Transactional and transaction propagation. Here is some info about the simplest scenario that most developer use.

When a Component/Service/Controller has @Transactional Spring will wrap it in a proxy (think decorator pattern), which will create thread local state, to house transaction information and link it to the @PersistenceContext EntityManagers . When the proxy completes the call to your @Transactional method, it will commit the transaction. Since this uses thread local state any @PersistenceContext annotated EntityManager which is used inside your @Transactional method, or any method it invokes, even methods in other beans will share the same transaction and persistence context.

In order to understand update better lets look at what happens when an entity is loaded in JPA. When you load an entity, the persistence context saves a copy, and when the transaction commits, it run through all managed entities and compare them to the copy from when it was loaded, based on this it figures out which update statements to send to the database. So when you load an entity and modify it, you don't have to do anything (except let the transaction commit) to update the database. When you persist a new entity, you add it to the internal collection of managed entities, and if you send the entity to a method that modifies it this will also end up in the database, as long as the modification happens before the transaction commits, and the entity becomes detached.

This is only the top of the iceberg, once you start talking about the different propagation types, manually calling flush or queries that trigger pre-query flush, it can get quite complicated. In my experience JPA is one of the most underestimated java technologies, on the surface it looks so simple, but if you don't understand the fundamentals, you can spend days understanding/debugging the errors you get.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM