Features/concepts of transactions
- Atomicity: “atom” means “indivisible”. The atomicity of a transaction refers to the fact that multiple operations involved in a transaction are logically indispensable. The atomicity of a transaction requires that all operations in a transaction either execute or none of them.
- Consistency: Consistency refers to data consistency. In particular, all data is in a consistent state that meets service rules. The consistency principle requires that no matter how many operations are involved in a transaction, the data must be correct before and after the transaction. If one or more operations fail during a transaction, all other operations must be undone to restore the data to the state before the transaction was executed. This is called rollback.
- Isolation: During the actual operation of an application, transactions tend to execute concurrently, so it is likely that many transactions will process the same data at the same time, so each transaction should be isolated from others to prevent data corruption. The principle of isolation requires that multiple transactions execute concurrently without interfering with each other.
- Durability: Durability requires that modifications to data persist permanently after transactions complete, unaffected by system errors or other contingencies. Normally, changes made by transactions to data should be written to persistent storage.
The jar package
<! --1. Configure a connection pool-->
<bean id="comboPooledDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="root"></property>
<property name="password" value= "123456"></property>
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/tx"></property>
</bean>
<! --2. Add, delete, change and check JdbcTemplate of the database-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="comboPooledDataSource"></property>
</bean>
<! --Configure transaction facets; Control the connection pool-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="comboPooledDataSource"></property>
</bean>
<! --Enable annotation-based transactions. Depends on the TX namespace transaction-manager: specifies which transaction manager is-->
<tx:annotation-driven/>Copy the code
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
/ * *Public int getPrice(String isbn); public int getPrice(String isbn); [2] Public void updateStock(String isbn); [3] Public void updateBalance(int price,String user); *@authorlfy ** /
@Repository
public classBookDao { @Autowired JdbcTemplate jdbcTemplate;/ * *Public int getPrice(String isbn); public int getPrice(String isbn); * Operation: book* /
public intgetPrice(String isbn){ String sql= "select price from book where isbn=?"; Integer price= jdbcTemplate.queryForObject(sql, Integer.class, isbn);
returnprice; };/ * *Public void updateStock(String isbn); public void updateStock(String isbn); * Action: book_stock* /
public voidupdateStock(String isbn){ String sql= "UPDATE book_stock SET stock=stock-1 WHERE isbn=?"; jdbcTemplate.update(sql, isbn); }/ * *Public void updateBalance(int price,String user); public void updateBalance(int price,String user); * Reduce the balance of the user; Account * String user: user name to reduce the balance * int price: how much to reduce (the amount reduced is the book price)* /
public void updateBalance(intprice,String user){ String sql= "update account set balance = balance-? where username=?"; jdbcTemplate.update(sql, price,user); }public voidupdatePrice(String isbn){ String sql= "update book set price = 999 WHERE isbn=?"; jdbcTemplate.update(sql, isbn); }}Copy the code
Transaction annotations are primarily added to the Service layer to implement transaction operations using Aop:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
importcom.atguigu.dao.BookDao; @Servicepublic classBookService { @Autowired BookDao bookDao; @Transactional(noRollbackFor=ArithmeticException.class, timeout=3,propagation=Propagation.REQUIRES_NEW)
public void checkout(String username,String isbn){
//Find out book prices
int price = bookDao.getPrice(isbn);
//1. Deduct the balance of users
bookDao.updateBalance(price, username);
//Reduce the inventory of books
bookDao.updateStock(isbn);
//Thread.sleep(3000);
//new FileInputStream("D://ahahahah//aa.txt");System.out.println(" Checkout complete...."); } @Transactional(propagation=Propagation.REQUIRED,timeout=3)
public void updatePrice(String isbn){
try{ Thread.sleep(3000); }catch(InterruptedException e) { e.printStackTrace(); } bookDao.updatePrice(isbn); }}Copy the code
Spring transaction manager
Properties of transaction control:
Propagation: the propagation of transactions; We can specify the relationship between large and small transactions through control;
Propagation (in the case of a shared transaction, the property configuration of a large transaction is propagated to a small transaction)+ behavior (whether or not a shared transaction is shared).
- Dirty read: Data is rolled back before it is committed during the same transaction.
- Non-repeatable read: Data is read differently for multiple times during the same transaction.
- Phantom read: During the same transaction, data is read several times and records are found to be fewer or more.
Essentially one reads again and one revises;
The database system must have the ability to isolate the individual transactions running concurrently so that they do not interfere with each other and avoid various concurrency problems. The degree to which a transaction is isolated from other transactions is called the isolation level. The SQL standard defines multiple transaction isolation levels, which correspond to different interference levels. The higher the isolation level, the better the data consistency, but the weaker the concurrency.
① READ UNCOMMITTED: READ UNCOMMITTED
Allow Transaction01 to read uncommitted changes in Transaction02.
② READ COMMITTED
Requires Transaction01 to read only changes that Transaction02 has committed.
REPEATABLE READ
Ensure that Transaction01 can read the same value from a field multiple times, that is, prohibit other transactions from updating the field while Transaction01 is executing.
④ Serialization: SERIALIZABLE
Ensure that Transaction01 can read the same row from a table multiple times, and prohibit other transactions from adding, updating, or deleting the table while Transaction01 is executing. Can avoid any concurrency problems, but performance is very poor.
(5) The ability of each isolation level to solve concurrency problems is shown in the following table
⑥ Support for transaction isolation level by various database products
Specify the transaction isolation level in Spring
annotations
When you use the @Transactional annotation to declaratively manage transactions, you can set the isolation level in the isolation attribute of @Transactional
XML
In Spring 2.x transaction notifications, you can specify the isolation level in the <tx: Method > element
An exception that triggers a transaction rollback
The default
It is rolled back when a RuntimeException or Error is caught, but not when a compile-time exception is caught.
Settings via
annotations
@ Transactional annotation
- RollbackFor property: Specifies the type of exception that must be rolled back when encountered
- NoRollbackFor attribute: Specifies the type of exception that will not be rolled back when encountered
XML
In Spring 2.x transaction notifications, you can specify rollback rules in the <tx:method> element. If there is more than one exception, separate it with a comma.
Timeout and read-only properties of the transaction
Introduction to the
Because transactions can acquire locks on rows and tables, long transactions consume resources and have an impact on overall performance.
If a transaction only reads data but does not modify it, the database engine can optimize the transaction.
Timeout transaction attribute: How long a transaction can remain in place before forced rollback. This prevents long running transactions from hogging resources.
Read-only transaction property: Indicates that the transaction reads data but does not update data, which helps the database engine optimize the transaction.
Set up the
annotations
@ Transaction annotations
XML
In Spring 2.x transaction notifications, timeout and read-only attributes can be specified in the <tx:method> element
For a more complete XML configuration:
<?The 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:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<context:component-scan base-package="com.atguigu"></context:component-scan>
<! --1. Configure a connection pool-->
<bean id="comboPooledDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="root"></property>
<property name="password" value= "123456"></property>
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/tx"></property>
</bean>
<! --2. Add, delete, change and check JdbcTemplate of the database-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="comboPooledDataSource"></property>
</bean>
<! --3. Configure transaction facets. Control the connection pool-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="comboPooledDataSource"></property>
</bean>
<! --4. Enable annotation-based transactions. Depends on the TX namespace transaction-manager: specifies which transaction manager is-->
<! -- <tx:annotation-driven/> -->
<! --Xml-based transaction configuration; Aop and TX namespaces are required-->
<! --TransactionManager transaction facets-->
<aop:config>
<! --Specifies which methods the transaction manager should access for transaction control-->
<aop:pointcut expression="execution(* com.soyoungboy.service.*.*(..) )" id="txPoint"/>
<! --Aop :advisor: Pointcut-ref: Cuts into a transaction using the specified pointcut expression-->
<aop:advisor advice-ref="myTxAdvice" pointcut-ref="txPoint"/>
</aop:config>
<! --Use tx namespaces and configurations (transaction recommendations, transaction attributes, transaction enhancement); Id ="myTxAdvice" : < AOP :advisor advice-ref="myTxAdvice" transaction-manager="transactionManager": specify which transaction manager to configure-->
<tx:advice id="myTxAdvice" transaction-manager="transactionManager">
<tx:attributes>
<! --Specify transaction methods: represents that all methods are transaction methods-->
<tx:method name= "*"/>
<tx:method name="checkout" rollback-for="java.lang.Exception"/>
<tx:method name="updatePrice" propagation="REQUIRES_NEW"/>
<! --Those that begin with GET are optimized by reading only-->
<tx:method name="get*" read-only="true"/>
</tx:attributes>
</tx:advice>
<! --Transaction control based on XML configuration is a bit more-->
</beans>Copy the code