Spring's declarative transactions

Source: Internet
Author: User
Tags ming

Before you talk about declarative transactions, review the basic programmatic transactions

Programmatic transactions:
1. Get the Connection object
Connection conn = Jdbcutils.getconnection ();
try {
2. Open transaction: Cancel Auto-commit
Conn.setautocommit (FALSE);
3. Performing Database operations
Chain.dofilter (REQ,RESP);
4. Commit a transaction
Conn.commit ();
}catch (Exception e) {
5. Rolling back a transaction
Conn.rollback ();

}finally{
6. Releasing Resources
}

Then talk about spring's declarative transactions
Examples of scenarios:

Xiao Ming has 1000 yuan, from the self-help bookstore to buy a price of 100, inventory of 200 of the "kingdoms".

Normal trading, Xiao Ming balance is now 900 yuan, bookstore inventory and 199.

If in the process of Xiao Ming buys a book, the transaction appears unusual, Xiao Ming spent 100 yuan, the machine fails to give the book, namely bookstore this book's inventory not to reduce.

This is obviously the loss of Xiao Ming, the transaction is unreasonable. At this point, the deal should be "canceled" immediately, i.e. the transaction cannot be passed.

In the program is said: Xiao Ming's spending and inventory reduction should be placed in

In one transaction, there is no normal execution, the entire program does not execute (not to the database to perform operations).

By Program implementation:

Create a Dynamic Web project
1. Add a jar Package
Com.springsource.net.sf.cglib-2.2.0.jar
Com.springsource.org.aopalliance-1.0.0.jar
Com.springsource.org.aspectj.weaver-1.6.8.release.jar
Commons-logging-1.1.3.jar
Spring-aop-4.0.0.release.jar
Spring-aspects-4.0.0.release.jar
Spring-beans-4.0.0.release.jar
Spring-context-4.0.0.release.jar
Spring-core-4.0.0.release.jar
Spring-expression-4.0.0.release.jar
Spring-jdbc-4.0.0.release.jar
Spring-orm-4.0.0.release.jar
Spring-tx-4.0.0.release.jar

Then the MySQL driver package is the C3P0 jar package:
C3p0-0.9.1.2.jar
Mysql-connector-java-5.1.37-bin.jar
2. Create a copy of the Jdbc.properties file
Jdbc.user=root
jdbc.passowrd=123456
Jdbc.url=jdbc:mysql://localhost:3306/tx
Jdbc.driver=com.mysql.jdbc.driver

3. Configure the data source in the spring configuration file
<!--introduce external properties files--
<context:property-placeholder location= "Classpath:jdbc.properties"/>
<!--configuring data sources-
<bean id= "Combopooleddatasource" class= "Com.mchange.v2.c3p0.ComboPooledDataSource" >
<property name= "user" value= "${jdbc.user}" ></property>
<property name= "Password" value= "${JDBC.PASSOWRD}" ></property>
<property name= "Jdbcurl" value= "${jdbc.url}" ></property>
<property name= "Driverclass" value= "${jdbc.driver}" ></property>
</bean>

4. Test the data source:
public class Testdatasource {
Private ApplicationContext IOC = new Classpathxmlapplicationcontext ("Applicationcontext.xml");
@Test
public void Test () throws SQLException {
DataSource bean = Ioc.getbean (datasource.class);
System.out.println (Bean.getconnection ());
}

}
5. Configure JdbcTemplate:
<bean id= "JdbcTemplate" class= "Org.springframework.jdbc.core.JdbcTemplate" >
<property name= "DataSource" ref= "Combopooleddatasource" ></property>
</bean>

6. Creating a DAO Class
<!--set the scanned package--
<context:component-scan base-package= "com.neuedu" ></context:component-scan>

@Repository
public class Bookdao {
@Autowired
Private JdbcTemplate JdbcTemplate;


public int FINDPRICEBYISBN (String ISBN) {
String sql = "Select Price from book WHERE ISBN =?";
Integer price = Jdbctemplate.queryforobject (sql, Integer.class, ISBN);
return price;
}
}

[2] According to the value of ISBN to reduce the inventory of books, assuming that only buy 1 books each time
public void Updatestockbyisbn (String ISBN) {
String sql = "UPDATE book_stock SET stock = stock-1 WHERE ISBN =?";
Jdbctemplate.update (sql, ISBN);
}
[3] Reduce the balance in the user account according to the user name, the amount of the reduction is the price of the book
public void UpdateBalance (String username,int price) {
String sql = "UPDATE account SET balance = balance-?" WHERE username =? ";
Jdbctemplate.update (SQL, price,username);
}
7. Create the service layer:
@Service
public class Bookservice {
@Autowired
Private Bookdao Bookdao;

public void Docash (String isbn,string username) {
int price = BOOKDAO.FINDPRICEBYISBN (ISBN);
BOOKDAO.UPDATESTOCKBYISBN (ISBN);
Bookdao.updatebalance (username, price);
}
}
8. Note: The three methods called in the Docash method above should be in the same transaction, either successfully at the same time, or fail at the same time!
Set it up first:
Then test the Docash method in the service as usual:
public class Testdatasource {
Private ApplicationContext IOC = new Classpathxmlapplicationcontext ("Applicationcontext.xml");
Private Bookdao bean = Ioc.getbean (bookdao.class);
Private Bookservice Bookservice = Ioc.getbean (Bookservice.class);

@Test
public void test04 () throws SQLException {
Bookservice.docash ("ISBN-001", "Tom");
}
}

Because the method is not in the transaction at this time, if the Docash method calls the method of DAO layer, there is an error in the middle position, it will cause some data to get rid of, and
The other part of the data is not changed, this is troublesome, so at this time should join the transaction mechanism!


9. If you want to turn on transactions, you need to configure the transaction manager in spring's configuration file

<!--Configure the transaction manager and configure the data source for the transaction manager! -
<bean id= "Datasourcetransactionmanager" class= " Org.springframework.jdbc.datasource.DataSourceTransactionManager ">
<property name= "DataSource" ref= "Combopooleddatasource" ></property>
</bean>
<!--to turn on annotation-based declarative transaction functionality, you need to set the Transaction-manager property--
<!--If the transaction manager's ID is exactly the default value of Transaction-manager TransactionManager, you can omit-
<tx:annotation-driven transaction-manager= "Datasourcetransactionmanager"/>

Then add: @Transactional Annotations on the service layer's Docash method to open the transaction! It is important to note that transactions are generally added to the service layer!


Database operations for the entire business logic:
[1] According to the value of the ISBN query the price of the book
[2] According to the value of ISBN to reduce the inventory of books, assuming that only buy 1 books each time
[3] Reduce the balance in the user account according to the user name, the amount of the reduction is the price of the book


Summary: Transactions can be divided into programmatic and declarative transactions

Declarative transactions
① Fundamentals: AOP
[1] Pre-notification: Open transaction
[2] Return notification: Commit TRANSACTION
[3] Exception notification: ROLLBACK TRANSACTION
[4] Post notification: releasing resources
② transaction Manager

③ Importing Jar Packages
[1] The jar package required by the IOC container
[2] The jar packages required by AOP
[3] Jar packages required for jdbctemplate operation
[5] MySQL Driver and c3p0

④ Configuration
[1] Configuring the data source
[2] Configuring the JdbcTemplate and assembling the data source
[3] Configuring the transaction manager and assembling the data source
<bean id= "Datasourcetransactionmanager" class= " Org.springframework.jdbc.datasource.DataSourceTransactionManager ">
<property name= "DataSource" ref = "DataSource"/>
</bean >
[4] Turn on annotation-based declarative transaction functionality
<tx:annotation-driven Transaction-manager = "Datasourcetransactionmanager"/>
If the ID of the transaction manager's Bean is exactly the default value of Transaction-manager TransactionManager, you can omit the

[5] Adding @transactional annotations to Transaction methods



4. Settings for transaction properties
The propagation behavior of ① affairs
Isolation level for ② transactions
③ transactions are not rolled back according to what exception
④ The Timeout property of a transaction
⑤ A read-only property of a transaction


① The propagation behavior of a transaction [see Chapter 8th World Document]
[1] Explanation: A transaction runs in another method with a transaction, then the current method is to open a new transaction or run in the original transaction.
[2] Sets the transaction method when invoking other transactional methods, how its own transaction is propagated to the called method. [Default is required]
[3] Setting mode

Case Demo:
Add a method to the above DAO to demonstrate the transaction!
To test the propagation behavior of a transaction, you need to add a database operation
public void Updateprice (String ISBN, int. price) {
String sql = "UPDATE book SET price =?" WHERE ISBN =? ";
Jdbctemplate.update (SQL, PRICE,ISBN);
}

Similarly, add a method to the service class as follows:
@Transactional
public void Updateprice (String ISBN, int. price) {
Bookdao.updateprice (ISBN, Price);
}
At this point there are two transaction methods in the current service class, and we now create a new service class, join the IOC container, and inject bookservice,
Then create a new transaction method, as follows:
@Component
public class Multitx {
@Autowired
Private Bookservice Bookservice;

@Transactional
public void Multitx () {
Bookservice.docash ("ISBN-003", "Tom");
Bookservice.updateprice ("ISBN-005", 888);
}
}

To demonstrate that the other two methods called in the service method are not transactions using the current service method, here we will call the second method of the service method
Make an exception and see if the first service method called by the service method is rolled back!

Set the data in the table first:
UPDATE ' account ' SET balance = 10000;
UPDATE book_stock SET stock = 1000;
UPDATE book SET price = 1000;

Test with the test class: Test it again, then complete an exception test:

public class Testdatasource {
Private ApplicationContext IOC = new Classpathxmlapplicationcontext ("Applicationcontext.xml");
Private Bookdao bean = Ioc.getbean (bookdao.class);
Private Bookservice Bookservice = Ioc.getbean (Bookservice.class);
Private Multitx MULTITX = Ioc.getbean (Multitx.class);
@Test
public void test04 () throws SQLException {
MULTITX.MULTITX ();
}
}

You will find that the @transactional annotation uses the Propagation property by default required!
At this point, you can add the Propagation=propagation.requires_new property to the two methods in the Bookservice class, which is as follows:
@Transactional (propagation=propagation.requires_new)

Then execute the test method that has the exception just now!



② the isolation level of a transaction: used to resolve concurrency problems [break point in the middle of the method of obtaining prices two times]
Isolation=isolation. read_committed

Restore the data in the data table first:
UPDATE ' account ' SET balance = 10000;
UPDATE book_stock SET stock = 1000;
UPDATE book SET price = 1000;
Modify the Docash method in the service class to: "That is two times get the price!" 】
@Transactional (propagation=propagation.requires_new)
public void Docash (String isbn,string username) {
int price = BOOKDAO.FINDPRICEBYISBN (ISBN);
System.out.println ("Price1:" +price);
BOOKDAO.UPDATESTOCKBYISBN (ISBN);
Bookdao.updatebalance (username, price);

Price = BOOKDAO.FINDPRICEBYISBN (ISBN);
System.out.println ("Price2:" +price);
}
Call the Docash method in the Bookservice class in the test method, and then in the Docash method two times to get the middle break point of the price method, you will find
The first time is 1000 yuan, then we modified the database, read out the 1000 yuan, this is because the database default isolation level is REPEATABLE READ!

If we add a isolation property to the transaction annotations on the Docash method, as follows:
@Transactional (propagation=propagation.requires_new,isolation=isolation.read_committed)
public void Docash (String isbn,string username) {
int price = BOOKDAO.FINDPRICEBYISBN (ISBN);
System.out.println ("Price1:" +price);
BOOKDAO.UPDATESTOCKBYISBN (ISBN);
Bookdao.updatebalance (username, price);

Price = BOOKDAO.FINDPRICEBYISBN (ISBN);
System.out.println ("Price2:" +price);
}
You will find that if you break a point between two fetch prices and then change the value, you will read a different effect, stating that the isolation level of the transaction is set to take effect!


③ transactions are not rolled back according to what exception
By default, an exception is rolled back, and the Norollbackfor property can set what exception does not roll back:
Norollbackfor=arithmeticexception.class

@Transactional (Propagation=propagation.requires_new,
Isolation=isolation.read_committed,
Norollbackfor=arithmeticexception.class)
public void Docash (String isbn,string username) {
int price = BOOKDAO.FINDPRICEBYISBN (ISBN);
System.out.println ("Price1:" +price);
BOOKDAO.UPDATESTOCKBYISBN (ISBN);
Bookdao.updatebalance (username, price);
System.out.println (10/0);//out of exception information
}

④ Transaction Timeout Property "Timeout=3"
[1] A database transaction consumes database resources during execution, so if a transaction takes too long to execute,
This causes the resource to be occupied for a long time, affecting the execution of other transactions. [Dead Loop, network problem]

[2] You can set the Timeout property to rollback a transaction that is not completed after a time-out, which is equivalent to undoing the operation.
@Transactional (Propagation=propagation.requires_new,
Isolation=isolation.read_committed,
Norollbackfor=arithmeticexception.class,
timeout=3)
public void Docash (String isbn,string username) {
int price = BOOKDAO.FINDPRICEBYISBN (ISBN);
System.out.println ("Price1:" +price);
BOOKDAO.UPDATESTOCKBYISBN (ISBN);
try {
Thread.Sleep (1000*5);
} catch (Interruptedexception e) {
TODO auto-generated Catch block
E.printstacktrace ();
}
Bookdao.updatebalance (username, price);
}

⑤ transaction Read-only property "Readonly=true"
The database optimizes the transaction, and if it is a query operation, the database can be targeted for optimization. We can set the transaction properties by setting the
Tells the database that the current operation is a read-only operation and is easy for the database to optimize.


5. XML-based declarative transactions
<!--Configure declarative transactions based on XML files--
<aop:config>
<!--Configure Pointcut expressions--
<aop:pointcut expression= "Execution (* com.neuedu.tx.service.bookservice.* (String, String))" id= "Txpointcut"/ >
<!--link the transaction pointcut with the configuration of the transaction recommendations-
<aop:advisor advice-ref= "booktransaction" pointcut-ref= "Txpointcut"/>
</aop:config>
<!--SET transaction Properties--
<tx:advice id= "booktransaction" transaction-manager= "Datasourcetransactionmanager" >
<tx:attributes>
<tx:method name= "Docash"
propagation= "REQUIRED"
isolation= "Read_committed"
Read-only= "false"
No-rollback-for= "Java.lang.ArithmeticException"
timeout= "3"/>
<!--unify a class of methods to read-only
<tx:method name= "get*" read-only= "true"/>
<tx:method name= "find*" read-only= "true"/>
<tx:method name= "query*" read-only= "true"/>
</tx:attributes>
</tx:advice>



Spring's declarative transactions

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.