Transaction management is critical for enterprise applications, and it can also ensure data consistency when anomalies occur.
Two ways to manage spring transactions
Spring supports both programmatic transaction management and declarative transaction management.
- Programmatic Transactions use transactiontemplate or use the underlying platformtransactionmanager directly. For programmatic transaction management, Spring recommends the use of transactiontemplate.
- declarative transactions are built on the AOP. The essence is to intercept the method before and after it, and then create or join a transaction before the target method starts, committing or rolling back the transaction according to execution after the target method is executed. The greatest advantage of declarative transactions is that you do not need to programmatically manage transactions, so that you do not need to doping transaction-managed code in your business logic code, just make relevant transaction rule declarations in the configuration file (or through @transactional annotations). You can apply transaction rules to the business logic.
It is obvious that declarative transaction management is better than programmatic transaction management, which is the non-intrusive development approach advocated by spring. Declarative transaction management makes business code non-polluting, a common Pojo object that can be fully transactional supported with annotations. The only disadvantage of declarative transactions, compared to programmatic transactions, is that its finest granularity only works at the method level and does not work like a programmatic transaction at the code block level. But even with this requirement, there are many workarounds, such as the ability to separate code blocks that require transaction management into methods, and so on.
There are two common ways of declarative transaction management, one is an XML configuration file based on the TX and AOP namespaces, and the other is based on @transactional annotations. The annotation-based approach is obviously easier to use and more refreshing.
Spring Transaction Features
Spring all transaction management policy classes inherit from the org.springframework.transaction.PlatformTransactionManager
interface.
Where TransactionDefinition
the interface defines the following attributes:
Transaction ISOLATION LEVEL
Isolation level refers to the degree of isolation between several concurrent transactions. Five constants representing the isolation level are defined in the Transactiondefinition interface:
- Transactiondefinition.isolation_default: This is the default value that represents the default isolation level for using 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 that has been modified by another transaction but has not yet been committed. This level does not prevent dirty reads, non-repeatable reads, and Phantom reads, so the isolation level is rarely used. For example, PostgreSQL does not actually have this level.
- Transactiondefinition.isolation_read_committed: This isolation level indicates that a transaction can only read data that has been committed by another transaction. This level prevents dirty reads, which is the recommended value in most cases.
- Transactiondefinition.isolation_repeatable_read: This isolation level indicates that a transaction can repeatedly execute a query multiple times throughout the process, and that the records returned are the same each time. This level protects against dirty reads and non-repeatable reads.
- Transactiondefinition.isolation_serializable: All transactions are executed one after the other, so that there is absolutely no possibility of interference between transactions, that is, the level prevents dirty reads, non-repeatable reads, and Phantom reads. However, this will severely affect the performance of the program. This level is not normally used.
Transactional propagation behavior
The so-called transaction propagation behavior is that if a transaction context already exists before the current transaction is started, there are several options to specify the execution behavior of a transactional method. The transactiondefinition definition includes the following constants that represent propagation behavior:
- Transactiondefinition.propagation_required: If a transaction is currently present, the transaction is joined and a new transaction is created if there is no current transaction. This is the default value.
- Transactiondefinition.propagation_requires_new: Creates a new transaction and suspends the current transaction if a transaction is currently present.
- Transactiondefinition.propagation_supports: If a transaction is currently present, the transaction is joined, and if no transaction is currently present, it will continue in a non-transactional manner.
- Transactiondefinition.propagation_not_supported: Runs in a non-transactional manner, suspending the current transaction if a transaction is currently present.
- Transactiondefinition.propagation_never: Runs in a non-transactional manner and throws an exception if a transaction is currently present.
- Transactiondefinition.propagation_mandatory: If a transaction is currently present, the transaction is joined and an exception is thrown if there is no current transaction.
- Transactiondefinition.propagation_nested: If a transaction is currently present, create a transaction to run as a nested transaction for the current transaction, or if there is no current transaction, The value is equivalent to transactiondefinition.propagation_required.
Transaction timeout
The so-called transaction timeout is the maximum time a transaction is allowed to execute, and if the time limit is exceeded but the transaction is not completed, the transactions are automatically rolled back. The value of int in transactiondefinition represents the time-out, in seconds.
The default setting is the timeout value for the underlying transaction system, or none if the underlying database transaction system does not have a timeout value set.
Spring Transaction rollback rules
By default, spring rolls back the transaction only if the exception is thrown as a run-time unchecked exception, which is the subclass of RuntimeException that throws the exception (errors also causes the transaction to be rolled back), while throwing a checked exception does not cause the transaction to be rolled back. You can explicitly configure which exceptions are thrown when the transaction is rolled back, including the checked exception. You can also explicitly define those exceptions that are thrown without rolling back the transaction. You can also programmatically use the Setrollbackonly () method to indicate that a transaction must be rolled back, and that the only action you can perform after the call to Setrollbackonly () is to rollback.
Using MyBatis as an example, declarative transactional configuration based on annotations
1. Add TX namespace
xmlns:tx="http://www.springframework.org/schema/tx"
2, open the transaction annotation support
<!-- 开启事务控制的注解支持 --> <tx:annotation-driven transaction-manager="transactionManager"/>
3, MyBatis automatically participate in the spring transaction management, no additional configuration, As long as the data source referenced by Org.mybatis.spring.SqlSessionFactoryBean is consistent with the data source referenced by Datasourcetransactionmanager.
<beanid="Sqlsessionfactory"class="Org.mybatis.spring.SqlSessionFactoryBean"> <propertyname="DataSource"ref="DataSource" /> <propertyname="Configlocation"> <value>Classpath:mybatis-config.xml</value> </property> </bean> <beanid="TransactionManager"class="Org.springframework.jdbc.datasource.DataSourceTransactionManager"> <propertyname="DataSource"ref="DataSource" /> </bean>
**4, using @transactional annotations * *
@Transactional can be used on interfaces, interface methods, classes, and class methods. When used on a class, all public methods of the class will have transactional properties of that type, and at the method level we can also use the annotation to override the class-level definition.
Although @Transactional annotations can be used on interfaces, interface methods, classes, and class methods, Spring does not recommend using this annotation on an interface or interface method, because it takes effect only when using an interface-based proxy. In addition, @Transactional annotations should only be applied to the public method, which is determined by the nature of Spring AOP. If you use @Transactional annotations on protected, private, or default visibility methods, this is ignored and no exceptions are thrown.
Using MyBatis as an example, a declarative transaction configuration based on an. xml file
<tx:adviceid="Advice"transaction-manager="TransactionManager"> <tx:attributes> <tx:methodname="update*"propagation="REQUIRED"read-only="false"rollback-for="Java.lang.Exception"/> <tx:methodname="Insert"propagation="REQUIRED"read-only="false"/> </tx:attributes> </tx:advice> <aop:config> <aop:pointcutid="Testservice"expression="Execution (* com.nnngu.service.mybatisservice.* (..))"/> <aop:advisoradvice-ref="Advice"pointcut-ref="Testservice"/> </aop:config>
Permanent update of this article address: https://github.com/nnngu/LearningNotes/blob/master/_posts/2018-03-22-Spring%E7%9A%84%E7%BC%96%E7%A8% 8b%e5%bc%8f%e4%ba%8b%e5%8a%a1%e5%92%8c%e5%a3%b0%e6%98%8e%e5%bc%8f%e4%ba%8b%e5%8a%a1.md
Spring's programmatic transactions and declarative transactions