Java EE traditional transactions have two strategies:
1. Global transactions
JTA global transaction
Transaction Ts = CTX. Lookup (..);
// Business logic
TX. Commit ();
TX. rollback ();
2. Local transactions
2.1.jdbc local transaction
Connection conn = getconnection (..);
Conn. setautocommit (false );
// Business logic
Conn. Commit ();
Conn. rollback ();
2.2.hibernate local transaction
Session S = getsession ();
Transaction Tx = S. begintransaction ();
// Business logic
TX. Commit ();
TX. rollback ();
Spring supports two transaction methods: programmatic transactions and clear transactions.
The Spring transaction policy is reflected through the platformtransactionmanager interface. The source code is as follows:
Public interface platfromtransactionmanager {
// Platform-independent transaction Acquisition Method
Transactionstatus gettransaction (transactiondefinition definition) throws transactionexception;
// Platform-independent transaction commit Method
Void commit (transactionstatus status) throws transactionexception;
// Platform-independent transaction rollback method
Void rollback (transactionstatus status) throws transactionexception;
}
Based on the different persistence APIs or frameworks used at the underlying layer, the main implementation classes of platformtransactionmanager are roughly as follows:
Datasourcetransactionmanager: Applicable to data persistence using JDBC and ibatis.
Hibernatetransactionmanager: applicable to the use of hibernate for data persistence operations.
Jpatransactionmanager: Applicable to data persistence operations using JPA.
There are also jtatransactionmanager, jdotransactionmanager, jmstransactionmanager, and so on. If we use JTA for transaction management, we can use JNDI and spring's jtatransactionmanager to obtain a datasource managed by the container. Jtatransactionmanager does not need to know datasource and other specific resources because it will use the global transaction management provided by the container. For other transaction managers, such as cetcetransactionmanager, the underlying data source must be provided as its attribute during definition, that is
Datasource. Sessionfactory corresponds to hibernatetransactionmanager, and entitymanagerfactory corresponds to jpatransactionmanager.
Programmatic Transaction Management: The program can directly obtain the transactionmanager bean in the container. This bean is always an instance of platformtransactionmanager.
1. Programming transaction management based on underlying APIs programming transaction management based on three core interfaces: platformtransactionmanager, transactiondefinition, and transactionstatus
2. transactiontemplate-based programming
Listing 6. example code of transactiontemplate-based transaction management: public class bankserviceimpl implements bankservice {private bankdao; private transactiontemplate ;...... public Boolean transfer (final long fromid, final long toid, final double amount) {return (Boolean) transactiontemplate.exe cute (New transactioncallback () {public object dointransaction (transactionstatus status) {object result; try { Result = bankdao. Transfer (fromid, toid, amount);} catch (exception e) {status. setrollbackonly (); Result = false; system. Out. println ("transfer error! ") ;}Return result ;}});}}
Listing 7. the configuration file <bean id = "bankservice" class = "footmark. spring. core. TX. programmatic. template. bankserviceimpl "> <property name =" bankdao "ref =" bankdao "/> <property name =" transactiontemplate "ref =" transactiontemplate "/> </bean>
Declarative Transaction Management: you do not need to write any transaction operation code in a Java program. You can use the AOP method to weave the enhanced processing. before the execution of the target method, the transaction starts. After the execution of the target method, the transaction ends. If an exception occurs, the transaction is rolled back.
1. Spring provides the transactioninterceptor class to implement declarative transaction management.
2. Although the previous declarative transaction is good, there is a very annoying problem: too many configuration files. We must configure a proxyfactorybean for each target object. In addition, although it can be reused through the Parent-Child bean method
Transactioninterceptor configuration, but the actual reuse probability is not high. In this way, with the target object itself, each service class may need to be configured with three <bean/>. As the business class increases, configuration files will become larger and larger, and management of configuration files becomes a problem. To alleviate this problem, Spring provides us
Transactionproxyfactorybean, used to combine the configuration of transactioninterceptor and proxyfactorybean into one
3.Declarative Transaction Management Based on the <TX> namespace
4.@ Transactional-based declarative Transaction Management
Display a configuration file
<? XML version = "1.0" encoding = "UTF-8"?> <Beans xmlns = "http://www.springframework.org/schema/beans" xmlns: xsi = "http://www.w3.org/2001/XMLSchema-instance" xmlns: context = "http://www.springframework.org/schema/context" xmlns: AOP = "http://www.springframework.org/schema/aop" xmlns: Tx = "http://www.springframework.org/schema/tx" xsi: schemalocation = "http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdh Ttp: // http://www.springframework.org/schema/tx/spring-tx.xsd "> <! -- Proxool data source --> <! -- <Bean id = "datasource" class = "org. springframework. JDBC. datasource. drivermanagerdatasource "> <property name =" driverclassname "> <value> Org. logicalcobwebs. proxool. proxooldriver </value> </property> <property name = "url"> <value> proxool. default </value> </property> </bean> --> <! -- C3p0 data source --> <bean id = "datasource" class = "com. mchange. v2.c3p0. combopooleddatasource "> <property name =" driverclass "value =" $ {hibernate. connection. driver_class} "/> <property name =" jdbcurl "value =" $ {hibernate. connection. URL} "/> <property name =" properties "> <props> <prop key =" user ">$ {hibernate. connection. username} </prop> <prop key = "password" >$ {hibernate. connection. password} </prop> </props> </propert Y> </bean> <! -- Sessionfactory --> <bean id = "sessionfactory" class = "org. springframework. orm. hibernate3.annotation. annotationsessionfactorybean "> <property name =" datasource "ref =" datasource "/> <property name =" packagestoscan "value =" com. fox. addressbook. model "/> <! -- <Property name = "mappingresources"> <list> <value> xxx/XXX/xxx. HBM. XML </value> </List> </property> --> <property name = "hibernateproperties"> <props> <prop key = "hibernate. dialect ">$ {hibernate. dialect} </prop> <prop key = "hibernate. show_ SQL ">$ {hibernate. show_ SQL} </prop> <prop key = "hibernate. format_ SQL ">$ {hibernate. format_ SQL} </prop> <prop key = "hibernate. hbm2ddl. auto ">$ {hibernate. hbm2ddl. auto} </prop> <prop key = "Hi Bernate. cache. provider_class ">$ {hibernate. cache. provider_class }</prop> <prop key = "hibernate. cache. use_query_cache ">$ {hibernate. cache. use_query_cache} </prop> <prop key = "hibernate. cache. use_second_level_cache ">$ {hibernate. cache. use_second_level_cache} </prop> </props> </property> </bean> <! -- Hibernatetemplate --> <bean id = "hibernatetemplate" class = "org. springframework. orm. hibernate3.hibernatetemplate "> <property name =" sessionfactory "ref =" sessionfactory "> </property> </bean> <! -- Configure Transaction Management --> <bean id = "transactionmanager" class = "org. springframework. orm. hibernate3.hibernatetransactionmanager "> <property name =" sessionfactory "ref =" sessionfactory "/> </bean> <! -- Configure annotations to manage transactions (cglib: proxy-target-class = "true") <TX: annotation-driven transaction-Manager = "transactionmanager" proxy-target-class = "true"/> --> <! -- Enable the configuration of transactional Behavior Based on Annotations <TX: annotation-driven transaction-Manager = "transactionmanager"/> --> <! -- Specify cglib --> <! -- <AOP: aspectj-autoproxy proxy-target-class = "true"/> --> <! -- Configure transaction Propagation Features --> <! -- Configure the transaction aspect and start automatic transaction management with <AOP: Advice> <TX: Advice id = "txadvice" transaction-Manager = "transactionmanager"> <TX: attributes> <TX: method name = "add *" propagation = "required"/> <TX: method name = "Edit *" propagation = "required"/> <TX: method Name = "Remove *" propagation = "required"/> <TX: method name = "Save *" propagation = "required"/> <TX: method Name = "Update *" propagation = "required"/> <TX: method name = "delete *" Propagation = "Required"/> <TX: method name = "batchupdate" propagation = "required"/> <TX: method Name = "defaultfolder" propagation = "required"/> <TX: method Name = "defaultfolder" propagation = "required" isolation = "default" no-rollback-for = "" Read-Only = "false" timeout = "-1" rollback- = ""/> <TX: method Name = "*" Read-Only = "true"/> </TX: Attributes> </TX: Advice> <! -- Configure the transaction start point --> <! --> <AOP: config> <AOP: pointcut id = "targetmethod" expression = "execution (* COM. fox. addressbook. dao. *. *(..)) "/> <AOP: Advisor advice-ref =" txadvice "pointcut-ref =" targetmethod "/> </AOP: config> </beans>
There are complicated rules for specifying the values of transaction properties, which is a headache in spring. The specific writing rules are as follows:
Propagation Behavior [, isolation level] [, read-only attribute]
[, Timeout attribute] [exceptions that do not affect submission] [, leading to rollback exceptions]
Propagation Behavior is the only property that must be set. Others can be ignored. Spring provides a reasonable default value.
The value of the Propagation Behavior must start with "propagation _", including: propagation_mandatory, propagation_nested, propagation_never, expiration, propagation_required, expiration, propagation_supports, and a total of seven values.
The value at the isolation level must start with "isolation _", including isolation_default, isolation_read_committed, isolation_read_uncommitted, isolation_repeatable_read, and isolation_serializable.
If the transaction is read-only, you can specify the read-only attribute using "readonly. Otherwise, we do not need to set this attribute.
The value of the timeout attribute must start with "timeout _", followed by an int value, indicating the timeout time, in seconds.