Recent projects have paid particular attention to the @Transactional of spring, and have looked it up online.
This article will take a closer look at spring's transaction management. It mainly introduces how @transactional works at the bottom. Later articles will describe: What traps are used for using transactions such as propagation (transactional propagation) and isolation (isolation), and how to avoid JPA and transaction management
It is important that the JPA itself does not provide any type of declarative transaction management. If JPA is used outside of the dependency injection container, the transaction must be implemented programmatically by the developer.
1 2 3 4 5 6 7 8 9 10 11 12 |
UserTransaction UTX = Entitymanager.gettransaction (); try {utx.begin (); Businesslogic (); Utx.commit (); } catch (Exception ex) {utx.rollback (); Throw ex; } |
Transaction management in this way allows the transaction scope to be clearly expressed in code, but it has the following drawbacks: Prone to duplicate code and errors can have a greater impact on errors difficult to debug and reproduce reduces the readability of the code base if the method calls other transactional methods how to handle it. Use spring @Transactional
With spring @Transactional, the code above is simplified to:
1 2 3 4 |
@Transactional public void Businesslogic () {... Use Entity manager inside a transaction ...} |
The code is more concise, more readable, and is currently the recommended way to handle transactions in spring.
Many important aspects, such as transaction propagation, can be handled automatically by using @transactional. In this case, if Businesslogic () calls another transaction method, the method determines how to join the running transaction, depending on the options.
One potential disadvantage of this powerful mechanism is that it hides the underlying operation, which is difficult to debug when it does not work properly. @Transactional meaning
On @transactional, one of the key points is to consider two independent concepts, each with their own scope and life cycle: persistence context (persistence contexts) database transaction (transaction)
The @Transactional itself defines the scope of a single transaction. This transaction is within the scope of the persistence context.
The persistence context in JPA is Entitymanager, and the internal implementation uses Hibernate Session (using hibernate as the persistent provider).
The persistence context is simply a synchronization object that records the state of a limited set of Java objects and ensures that changes to these objects are eventually persisted to the database.
This is a very different concept from a single transaction. An entity Manager can be used across multiple transactions , and this is really the case. Entitymanager When to span multiple transactions.
The most common scenario is when an app uses the open Session in view mode to handle lazy initialization exceptions, and the previous article describes the advantages and disadvantages of this approach.
In this case, multiple queries run by the view layer are in separate transactions, not single-transaction business logic, but these queries are managed by the same entity manager.
Another scenario is that the developer marks the persistence context as persistencecontexttype.extended, which means it can respond to multiple requests. How to define the relationship between Entitymanager and transaction.
This is selected by the app developer, but the most common way for JPA entity manager is "entity manager per application Transaction" (each transaction has its own entity manager) mode. The common methods for Entity manager injection are:
1 2 |
@PersistenceContext Private Entitymanager em; |
The default is "Entity Manager per transaction" mode. In this mode, if the entity Manager is used inside the @transactional method, the method runs in a single transaction. how @PersistenceContext work.
The problem with this is how @persistencecontext injects entity manager only when the container starts, assuming that the entity manager life cycle is short and requires multiple entity managers per request.
The answer is that it cannot: Entitymanager is an interface that is injected into the spring bean, not the entity manager itself, but rather the context aware proxy of the specific entity manager at runtime.
Typically the specific class used for the proxy is Sharedentitymanagerinvocationhandler, which can be confirmed by the debugger. so @transactional how to work.
The persistence context proxy that implements the Entitymanager interface is not the only part of declarative transaction management, and in fact contains three components: the slice transaction manager of the Entitymanager proxy itself transaction
Take a look at the three parts and the interplay between them. facets of a transaction
The facet of a transaction is a "around" slice, which can be called before and after the annotated business method. The concrete class for implementing facets is transactioninterceptor.
The facets of a transaction have two main responsibilities: at ' before ', the facets provide a point of call to determine whether the invoked business method should run within the scope of the transaction in progress or start a new independent transaction. At ' after ', the facets need to determine whether the transaction is committed, rolled back, or continues to run.
At ' before ', the transaction slice itself does not contain any decision logic, and the decision to start a new transaction is delegated to the transaction manager to complete. transaction manager
The transaction manager needs to address the following two questions: whether the new entity manager should be created. Whether a new transaction should start.
These need to be determined when the transaction plane ' before ' logic is invoked. The decision of the transaction manager is based on the following two points: whether the transaction is in the propagation property of the transaction method (for example, Requires_new always starts a new transaction)
If the transaction manager determines that a new transaction is to be created, it will: Create a new Entity Manager Entity manager bound to the current thread to get the connection from the database connection pool bind the connection to the current thread
Use the threadlocal variable to bind both the Entity manager and the database connection to the current thread.
Transactions run when they are stored in threads, and when they are no longer being used, the transaction manager decides whether to purge them.
Any part of the program can be fetched from the thread if it needs the current Entity manager and database connection. Entitymanager Proxy
Entitymanager proxy (described earlier) is the last part of the puzzle. When a business method calls Entitymanager.persist (), this is not called directly by entity Manager.
Instead, the business method invokes the proxy, which obtains the current entity manager from the thread, which is described previously by the transaction manager binding the entity manager to the thread.
Understanding the various parts of the @transactional mechanism, let's look at the common spring configurations that implement it. consolidation of three parts
How do you combine the three parts to make the transaction annotations work correctly? Define the Entity Manager factory first.
This allows the entity Manager proxy to be injected through persistent context annotations.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
@Configuration public class Entitymanagerfactoriesconfiguration { & nbsp; @Autowired private DataSource DataSource; @Bean (name = "Entitymanagerfactory") public Localcontainerentitymanagerfactorybean emf () { Localcontainerentitymanagerfactorybean emf = ... Emf.setdatasource (DataSource); Emf.setpackagestoscan ( New string[] {"Your.package" }); Emf.setjpavendoradapter ( new HibernateJpaVendorAdapter ()); return EMF; } } |
The next step is to implement the configuration transaction manager and apply the facets of the transaction in the @transactional annotated class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
@Configuration @EnableTransactionManagement public class transactionmanagersconfig { @Autowired entitymanagerfactory emf; @Autowired Private DataSource DataSource; @Bean (name = "TransactionManager") public Platformtransactionmanager TransactionManager () { Jpatransactionmanager TM = new Jpatransactionmanager (); Tm.setentitymanagerfactory (EMF); Tm.setdatasource (DataSource); return TM; } } |
Note @enabletransactionmanagement notifies spring that the class @Transactional annotated is surrounded by the facets of the transaction. So the @transactional can be used. Summary
The Spring declarative transaction management mechanism is very powerful, but it can be misused or prone to misconfiguration.
It is helpful to understand the internal work of the mechanism when it does not work properly or if it does not meet the expected running results.
The most important thing to remember is that there are two concepts to consider: the transaction and the persistence context, each with its own unreadable distinct life cycle.
Original link: Javacodegeeks translation: Importnew.com-hejiani
Link: http://www.importnew.com/12300.html
This is a translation of the article, very good ah, feel good please top.