Overview
Transaction management is crucial for enterprise applications, and it can ensure data consistency even if abnormal situations occur.
Spring Framework provides a consistent abstraction for transaction management, with its characteristics as follows:
Provide consistent programming models for different transaction APIs, such as JTA (Java Transaction API), JDBC, Hibernate, JPA (Java Persistence API and JDO (Java Data Objects)
Supports declarative transaction management, especially declarative transaction management based on annotations, which is simple and easy to use
Provides a simpler programming transaction management API than other transaction APIs such as JTA
Perfect integration with spring data access abstraction
Transaction management method
Spring supports two methods: programmatic transaction management and declarative transaction management.
Programmatic transaction management uses TransactionTemplate or directly uses the underlying PlatformTransactionManager. For programmatic transaction management, spring recommends using TransactionTemplate.
Declarative transaction management is built on AOP. Its essence is to intercept the method before and after, and then create or add a transaction before the target method begins. After executing the target method, the transaction is submitted or rolled back according to the execution situation. The biggest advantage of declarative transactions is that they do not need to manage transactions programmatically, so there is no need to dopant transaction management code in the business logic code. Just make relevant transaction rules declarations in the configuration file (or through @Transactional annotation) and you can apply transaction rules to the business logic.
Obviously, declarative transaction management is better than programmatic transaction management, which is exactly the non-invasive development method advocated by spring. Declarative transaction management keeps business code free from contamination. A normal POJO object can obtain complete transaction support by adding annotations. Compared with programming transactions, the only disadvantage of declarative transactions is that the latter's finest granularity can only act at the method level, and cannot be achieved as a programmatic transaction can act at the code block level. However, even with such a requirement, there are many workarounds, such as the code blocks that require transaction management can be independently processed, etc.
There are also two commonly used methods for declarative transaction management. One is the XML configuration file based on the tx and aop namespaces, and the other is based on the @Transactional annotation. Obviously, the annotation-based method is simpler and easier to use and more refreshing.
Automatic Commit (AutoCommit) and whether to automatically submit when the connection is closed
Automatic submission
By default, the database is in automatic submission mode. Each statement is in a separate transaction. When the execution of this statement is completed, if the execution is successful, the transaction is implicitly submitted.
If the execution fails, the transaction is implicitly rolled back.
For normal transaction management, a set of related operations is in a transaction, so the automatic commit mode of the database must be turned off. However, we don't have to worry about this, spring will set the automatic commit feature of the underlying connection to false.
org/springframework/jdbc/datasource/DataSourceTransactionManager.java
// switch to manual commit if necessary. this is very expensive in some jdbc drivers,// so we don't want to do it unnecessarily (for example if we've explicitly// configured the connection pool to set it already).if (con.getautocommit()) { txobject.setmustrestoreautocommit(true); if (logger.isdebugenabled()) { logger.debug("switching jdbc connection [" + con + "] to manual commit"); } con.setautocommit(false);}Some data connection pools provide settings to turn off automatic transaction commits, which are best to turn off when setting up the connection pool. However, C3P0 does not provide this feature and can only rely on spring to set it.
Because the JDBC specification stipulates that when the connection object is established, it should be in automatic commit mode, which is the default value across DBMS, and automatic commit must be explicitly turned off if necessary. C3P0 abides by this specification and allows the client code to explicitly set the required submission mode.
Whether to submit automatically when the connection is closed
When a connection is closed, what should be handled if there is an uncommitted transaction? The JDBC specification does not mention that the default policy of C3P0 is to roll back any uncommitted transactions. This is the right strategy, but there is no agreement among JDBC driver providers on this issue.
The autoCommitOnClose property of C3P0 is false by default, so there is no need to do not move it. Or you can explicitly set this property to false, which will be more clear.
Annotation-based declarative transaction management configuration
spring-servlet.xml
<!-- transaction support--><!-- PlatformTransactionMnager --><bean id="txManager"> <property name="dataSource" ref="dataSource" /></bean><!-- enable transaction annotation support --><tx:annotation-driven transaction-manager="txManager" />
Also add tx namespace in spring-servlet.xml
... xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" ...http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd ...
MyBatis automatically participates in spring transaction management without additional configuration. As long as the data source referenced by org.mybatis.spring.SqlSessionFactoryBean is consistent with the data source referenced by DataSourceTransactionManager, otherwise the transaction management will not work.
In addition, you need to download the dependency package aopalliance.jar and put it in the WEB-INF/lib directory. Otherwise, an exception will be reported when spring is initialized
java.lang.NoClassDefFoundError: org/aopalliance/intercept/MethodInterceptor
Spring transaction features
All transaction management policy classes in spring are inherited from org.springframework.transaction.PlatformTransactionManager interface
public interface PlatformTransactionManager {TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException; void commit(TransactionStatus status) throws TransactionException; void rollback(TransactionStatus status) throws TransactionException;}The TransactionDefinition interface defines the following characteristics:
Transaction isolation level
The isolation level refers to the degree of isolation between several concurrent transactions. Five constants representing isolation levels are defined in the TransactionDefinition interface:
TransactionDefinition.ISOLATION_DEFAULT: This is the default value, indicating the default isolation level used for the underlying database. For most databases, this value is usually TransactionDefinition.ISOLATION_READ_COMMITTED.
TransactionDefinition.ISOLATION_READ_UNCOMMITTED: This isolation level indicates that one transaction can read data modified by another transaction but has not yet been committed. This level does not prevent dirty reading, repetitive reading and phantom reading, so this isolation level is rarely used. For example, PostgreSQL does not actually have this level.
TransactionDefinition.ISOLATION_READ_COMMITTED: This isolation level means that one transaction can only read data that has been committed by another transaction. This level prevents dirty reading, which is also the recommended value in most cases.
TransactionDefinition.ISOLATION_REPEATABLE_READ: This isolation level indicates that a transaction can execute a query multiple times throughout the process, and the records returned are the same each time. This level prevents dirty and non-repeatable readings.
TransactionDefinition.ISOLATION_SERIALIZABLE: All transactions are executed one by one in sequence, so that there is no possibility of interference between transactions, that is, this level can prevent dirty reading, non-repeatable reading and phantom reading. But this will seriously affect the performance of the program. This level is not usually used.
Transaction communication behavior
The so-called transaction propagation behavior refers to that if a transaction context already exists before the current transaction is started, there are several options that can specify the execution behavior of a transactional method. The TransactionDefinition definition includes the following constants representing propagation behavior:
TransactionDefinition.PROPAGATION_REQUIRED: If a transaction is currently present, join the transaction; if there is currently no transaction, create a new transaction. This is the default value.
TransactionDefinition.PROPAGATION_REQUIRES_NEW: Creates a new transaction, and if the transaction currently exists, the current transaction will be suspended.
TransactionDefinition.PROPAGATION_SUPPORTS: Join the transaction if there is currently a transaction; if there is currently no transaction, it continues to run in a non-transactional manner.
TransactionDefinition.PROPAGATION_NOT_SUPPORTED: Runs in a non-transactional manner, and if a transaction currently exists, the current transaction will be suspended.
TransactionDefinition.PROPAGATION_NEVER: Runs in a non-transactional manner, throws an exception if a transaction is currently present.
TransactionDefinition.PROPAGATION_MANDATORY: Join the transaction if there is currently a transaction; if there is currently no transaction, an exception is thrown.
TransactionDefinition.PROPAGATION_NESTED: If a transaction is currently present, a transaction is created to run as a nested transaction of the current transaction; if there is no transaction, the value is equivalent to TransactionDefinition.PROPAGATION_REQUIRED.
Transaction timeout
The so-called transaction timeout refers to the maximum time allowed by a transaction. If the time limit is exceeded but the transaction has not been completed, the transaction will be automatically rolled back. In TransactionDefinition, the timeout is represented by the value of int, and its unit is seconds.
The default setting is the timeout value of the underlying transaction system. If the underlying database transaction system does not set the timeout value, then it is none, and there is no timeout limit.
Transaction read-only attributes
Read-only transactions are used in situations where the client code is read-only but does not modify data. Read-only transactions are used in optimization in specific scenarios, such as when using Hibernate.
The default is read and write transactions.
Spring transaction rollback rules
The recommended way to instruct spring transaction manager to roll back a transaction is to throw an exception within the context of the current transaction. The spring transaction manager catches any unhandled exceptions and then decides whether to roll back the transaction that throws the exception based on the rules.
By default, spring will only roll back the transaction if the exception thrown is a runtime unchecked exception, that is, the exception thrown is a subclass of RuntimeException (Errors will also cause transaction rollback), while throwing a checked exception will not cause transaction rollback.
It is possible to explicitly configure the transaction to roll back when those exceptions are thrown, including checked exceptions. It is also possible to clearly define those transactions that do not roll back when exceptions are thrown.
You can also programmatically use the setRollbackOnly() method to indicate that a transaction must be rolled back. The only thing you can do after calling setRollbackOnly() is rollback.
@Transactional annotation
@Transactional Properties
| property | type | describe |
|---|---|---|
| value | String | Optional qualifier descriptor, specifying the transaction manager to use |
| propagation | enum: Propagation | Optional transaction propagation behavior settings |
| isolation | enum: Isolation | Optional transaction isolation level settings |
| readOnly | boolean | Read and write or read-only transaction, default read and write |
| timeout | int (in seconds granularity) | Transaction timeout setting |
| rollbackFor | Class object array must be inherited from Throwable | Array of exception classes that cause transaction rollback |
| rollbackForClassName | Array of class names must be inherited from Throwable | Array of exception class names that cause transaction rollback |
| noRollbackFor | Class object array must be inherited from Throwable | An exception class array that does not cause transaction rollback |
| noRollbackForClassName | Array of class names must be inherited from Throwable | An array of exception class names that will not cause transaction rollback |
usage
@Transactional can act on interfaces, interface methods, classes and class methods. When acting on a class, all public methods of the class will have transaction properties of that type. At the same time, we can also use this annotation at the method level to override the class-level definition.
Although the @Transactional annotation can be applied to interfaces, interface methods, classes, and class methods, Spring recommends not to use this annotation on interfaces or interface methods, because this will only take effect when using an interface-based proxy. In addition, the @Transactional annotation should only be applied to the public method, which is determined by the nature of Spring AOP. If you use the @Transactional annotation on protected, private, or default visibility methods, this will be ignored and no exceptions will be thrown.
By default, only method calls from outside will be captured by the AOP proxy, that is, calling other methods inside this class inside the class will not cause transaction behavior, even if the called method is modified using the @Transactional annotation.
@Transactional(readOnly = true)public class DefaultFooService implements FooService {public Foo getFoo(String fooName) {// do something}// these settings have precedence for this method//The annotation attribute on the method will override the same attribute on the class annotation @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW) public void updateFoo(Foo foo) {// do something}}Summarize
The above is all the content of this article's interpretation of the usage of @Transactional annotation in spring, and I hope it will be helpful to everyone. Interested friends can continue to refer to other related topics on this site. If there are any shortcomings, please leave a message to point it out. Thank you friends for your support for this site!