Learning spring Things

Keywords: JDBC Spring Database Programming

Understanding things

Transaction, as you know, is a series of rigorous operations, either completed or revoked. Spring transaction manages the transaction mechanism of the Be based on underlying database itself. The foundation of database transaction is to master Spring transaction management. This article summarizes s Spring transactions.
Transactions have four characteristics of ACID. ACID is the abbreviation of Atomic, Consistency, Isolation and Durability.

  1. The most basic unit of operation for Atomicity transactions either succeeds or fails altogether, and it does not end in the middle. When a transaction fails in execution, it is rolled back to its pre-transaction state, as if the transaction had never been executed.
  2. Consistency Transaction Consistency means that the database must be in a consistent state before and after a transaction is executed. If the transaction is successfully completed, all changes in the system will be correctly applied and the system is in an effective state. If an error occurs in a transaction, all changes in the system will automatically roll back and the system will return to its original state.
  3. Isolation means that in a concurrent environment, when different transactions manipulate the same data at the same time, each transaction has its own complete data space. Changes made by concurrent firms must be isolated from changes made by any other concurrent firms. When a transaction looks at data updates, the state of the data is either the state before another transaction modifies it or the state after another transaction modifies it, and the transaction does not view the data in the intermediate state.
  4. Durability means that as long as the transaction ends successfully, the updates it makes to the database must be preserved permanently. Even if the system crashes, after restarting the database system, the database can restore to the state at which the transaction ended successfully.

The Propagation Characteristics of Transactions

Transaction propagation behavior is how to define the propagation of transactions between methods when multiple transaction methods are invoked. Spring defines communication behavior in 7:

  • (1) propagation_requierd: If there is no transaction at present, create a new one. If there is already a transaction, join it. This is Spring's default choice.
  • (2) propagation_support: Supports the current transaction, and if there is no current transaction, it is executed in a non-transactional manner.
  • (3) propagation_mandatory: With the current transaction, if there is no current transaction, an exception is thrown.
  • (4) propagation_required_new: Create a new transaction and suspend the current transaction if it currently exists.
  • (5) propagation_not_supported: Performs operations in a non-transactional manner, suspending the current transaction if it exists.
  • (6) propagation_never: Performs operations in a non-transactional manner, throwing exceptions if the current transaction exists.
  • (7) propagation_nested: If a transaction currently exists, it executes within the nested transaction. If there are no transactions currently, perform operations similar to propagation_required.

Understanding Dirty Reading, Illusive Reading and Non-repeatable Reading

Dirty reading

Dirty reading means that one thing reads data that has been modified by other things, but has not yet been submitted, and then transaction 1 rolls back. Now thing 2 reads invalid.

  1. Mary's original salary was 1000, and the financial staff changed Mary's salary to 8000, but did not submit a transaction.
  2. At the same time, Mary is reading her salary. Mary finds that her salary has changed to 8000, joyful! (dirty reading)
  3. When the finance found that the operation was wrong and the transaction was rolled back, Mary's salary changed to 1000.

Non-repeatable reading

When transaction 1 reads records, transaction 2 updates records and submits them. When transaction 1 reads again, it can see the modified records of transaction 2.

  1. In transaction 1, Mary read her salary of 1000 and the operation was not completed.
  2. In transaction 2, the financier modified Mary's salary to 2000 and submitted the transaction.
  3. In transaction 1, when Mary reads her salary again, the salary changes to 2000.

phantom read

When transaction 1 reads records, transaction 2 adds records and submits them. When transaction 1 reads records again, transaction 2 adds records.

  1. At present, there are 10 employees with a salary of 1000.
  2. Transaction 1, read all employees whose salary is 1000. A total of 10 records were read.
  3. Then another transaction inserts an employee record into the employee table, and the salary is 1000.
  4. Transaction 1 reads all the employees whose salary is 1000 again, and reads 11 records, which results in phantom reading.

Understanding the isolation level of things

  • ISOLATION_DEFAULT: This is the default isolation level, using the default transaction isolation level of the database. The other four correspond to the isolation level of JDBC.
  • READ UNCOMMITTED: Illusive reading, non-repeatable reading and dirty reading are allowed;
  • READ COMMITTED: Illusive reading and non-repeatable reading are allowed, but dirty reading is not allowed.
  • REPEATABLE READ: Hallucination is allowed, but non-repeatable and dirty reading is not allowed.
  • SERIALIZABLE: Illusive reading, non-repeatable reading and dirty reading are not allowed
  1. Propagation
  1. Transaction Communication Behavior
  1. PROPAGATION_REQUIRED -- Supports the current transaction, and if there is no transaction at present, creates a new one. This is the most common choice.
  2. PROPAGATION_SUPPORTS -- Supports the current transaction and executes in a non-transactional manner if there is no transaction at present.
  3. PROPAGATION_MANDATORY -- Supports the current transaction and throws an exception if there is no transaction at present.
  4. PROPAGATION_REQUIRES_NEW -- Create a new transaction and suspend the current transaction if it currently exists.
  5. PROPAGATION_NOT_SUPPORTED -- Performs operations in a non-transactional manner, suspending the current transaction if it exists.
  6. PROPAGATION_NEVER -- Executes in a non-transactional manner and throws an exception if a transaction currently exists.
  7. PROPAGATION_NESTED -- If a transaction currently exists, it executes within a nested transaction. If there is no transaction at the moment, do something similar to PROPAGATION_REQUIRED.
  1. Isolation
  1. Transaction isolation level
  1. @ Transactional(isolation = Isolation.READ_UNCOMMITTED) reading uncommitted data (dirty reading, non-repeatable reading) is not used at all.
  2. @ Transactional(isolation = Isolation.READ_COMMITTED) reads submitted data (unrepeatable and hallucinatory reads occur)
  3. @ Transactional(isolation = Isolation.REPEATABLE_READ) repeatable (hallucination occurs)
  4. @ Transactional(isolation = Isolation.SERIALIZABLE) serialization

Several Implementations of spring Transaction

  • Programming transaction management is the only option for POJO-based applications. We need to call beginTransaction(), commit(), rollback() and other transaction management-related methods in our code, which is programmable transaction management.
  • Declarative Transaction Management Based on Transaction Proxy FactoryBean Transaction Agent Factory
  • Be based on @Transactional Annotative Transaction Management
  • Configuring transactions based on Aspectj AOP

An example based on Transaction ProxyFactoryBean:

// Custom exception class
public class BuyStockException extends Exception {
 
	public BuyStockException() {
		super();
	}
 
	public BuyStockException(String message) {
		super(message);
	}
 
}


// 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:mvc="http://www.springframework.org/schema/mvc"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    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/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-aop-4.2.xsd
        ">
	
	<context:property-placeholder location="classpath:jdbc.properties"/>
	
	<!-- Registered Data Source C3P0 -->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"  >
		 <property name="driverClass" value="${jdbc.driverClass}"></property>
		 <property name="jdbcUrl"  value="${jdbc.url}"></property>
         <property name="user"  value="${jdbc.username}"></property>
         <property name="password" value="${jdbc.password}"></property>
	</bean>
	
	<bean id="accountDao" class="transaction.test2.dao.AccountDaoImpl">
		<property name="dataSource" ref="dataSource"/>
	</bean>
	
	<bean id="stockDao" class="transaction.test2.dao.StockDaoImpl">
		<property name="dataSource" ref="dataSource"/>
	</bean>
	
	<bean id="buyStockService" class="transaction.test2.service.BuyStockServiceImpl">
		<property name="accountDao" ref="accountDao"></property>
		<property name="stockDao" ref="stockDao"></property>
	</bean>
	
	
	<!-- Transaction Manager -->
	
	<bean id="myTracnsactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<!-- Transaction Agent Factory -->
	<!-- Generating Transaction Agent Objects -->
	<bean id="serviceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
		<property name="transactionManager" ref="myTracnsactionManager"></property>
		<property name="target" ref="buyStockService"></property>
		<property name="transactionAttributes">
			<props>
				<!-- main key Method is   
					ISOLATION_DEFAULT  Transaction isolation level
					PROPAGATION_REQUIRED  Communication behavior
				-->
				<prop key="add*">ISOLATION_DEFAULT,PROPAGATION_REQUIRED</prop>
				<!-- -Exception Represents the occurrence of a specified exception rollback.+Exception Represents the occurrence of a specified exception submission -->
				<prop key="buyStock">ISOLATION_DEFAULT,PROPAGATION_REQUIRED,-BuyStockException</prop>
			</props>
		</property>
		
	</bean>
	
	
</beans>

Declarative Transaction Management Based on @Transactional

// service Layer Method with @Transaction Annotation and Configuration Parameters
public class BuyStockServiceImpl implements BuyStockService{
 
	private AccountDao accountDao;
	private StockDao stockDao;
	
	@Transactional(isolation=Isolation.DEFAULT,propagation=Propagation.REQUIRED)
	@Override
	public void addAccount(String accountname, double money) {
		accountDao.addAccount(accountname,money);
		
	}
 
	@Transactional(isolation=Isolation.DEFAULT,propagation=Propagation.REQUIRED)
	@Override
	public void addStock(String stockname, int amount) {
		stockDao.addStock(stockname,amount);
		
	}
 
	public BuyStockServiceImpl() {
		// TODO Auto-generated constructor stub
	}
	
	@Transactional(isolation=Isolation.DEFAULT,propagation=Propagation.REQUIRED,rollbackFor=BuyStockException.class)
	@Override
	public void buyStock(String accountname, double money, String stockname, int amount) throws BuyStockException {
		boolean isBuy = true;
		accountDao.updateAccount(accountname, money, isBuy);
		if(isBuy==true){
			throw new BuyStockException("Abnormal purchase of shares");
		}
			stockDao.updateStock(stockname, amount, isBuy);
		
	}
 
	public AccountDao getAccountDao() {
		return accountDao;
	}
 
	public void setAccountDao(AccountDao accountDao) {
		this.accountDao = accountDao;
	}
 
	public StockDao getStockDao() {
		return stockDao;
	}
 
	public void setStockDao(StockDao stockDao) {
		this.stockDao = stockDao;
	}
}


// configuration file
<context:property-placeholder location="classpath:jdbc.properties"/>
	
	<!-- Register Data Sources C3P0 -->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"  >
		 <property name="driverClass" value="${jdbc.driverClass}"></property>
		 <property name="jdbcUrl"  value="${jdbc.url}"></property>
         <property name="user"  value="${jdbc.username}"></property>
         <property name="password" value="${jdbc.password}"></property>
	</bean>
	
	<bean id="accountDao" class="transaction.test3.dao.AccountDaoImpl">
		<property name="dataSource" ref="dataSource"/>
	</bean>
	
	<bean id="stockDao" class="transaction.test3.dao.StockDaoImpl">
		<property name="dataSource" ref="dataSource"/>
	</bean>
	
	<bean id="buyStockService" class="transaction.test3.service.BuyStockServiceImpl">
		<property name="accountDao" ref="accountDao"></property>
		<property name="stockDao" ref="stockDao"></property>
	</bean>
	
	
	<!-- Transaction Manager -->
	<bean id="myTracnsactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<!-- Enable transaction annotations -->
	<tx:annotation-driven transaction-manager="myTracnsactionManager"/>

Configuring transactions based on Aspectj AOP


public class BuyStockServiceImpl implements BuyStockService{
 
	private AccountDao accountDao;
	private StockDao stockDao;
	
	@Override
	public void addAccount(String accountname, double money) {
		accountDao.addAccount(accountname,money);
		
	}
 
	@Override
	public void addStock(String stockname, int amount) {
		stockDao.addStock(stockname,amount);
		
	}
 
	public BuyStockServiceImpl() {
		// TODO Auto-generated constructor stub
	}
	
	@Override
	public void buyStock(String accountname, double money, String stockname, int amount) throws BuyStockException {
		boolean isBuy = true;
		accountDao.updateAccount(accountname, money, isBuy);
		if(isBuy==true){
			throw new BuyStockException("Abnormal purchase of shares");
		}
			stockDao.updateStock(stockname, amount, isBuy);
		
	}
 
	public AccountDao getAccountDao() {
		return accountDao;
	}
 
	public void setAccountDao(AccountDao accountDao) {
		this.accountDao = accountDao;
	}
 
	public StockDao getStockDao() {
		return stockDao;
	}
 
	public void setStockDao(StockDao stockDao) {
		this.stockDao = stockDao;
	}
}

// configuration file
<context:property-placeholder location="classpath:jdbc.properties"/>
	
	<!-- Register Data Sources C3P0 -->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"  >
		 <property name="driverClass" value="${jdbc.driverClass}"></property>
		 <property name="jdbcUrl"  value="${jdbc.url}"></property>
         <property name="user"  value="${jdbc.username}"></property>
         <property name="password" value="${jdbc.password}"></property>
	</bean>
	
	<bean id="accountDao" class="transaction.test4.dao.AccountDaoImpl">
		<property name="dataSource" ref="dataSource"/>
	</bean>
	
	<bean id="stockDao" class="transaction.test4.dao.StockDaoImpl">
		<property name="dataSource" ref="dataSource"/>
	</bean>
	
	<bean id="buyStockService" class="transaction.test4.service.BuyStockServiceImpl">
		<property name="accountDao" ref="accountDao"></property>
		<property name="stockDao" ref="stockDao"></property>
	</bean>
	
	
	<!-- Transaction Manager -->
	<bean id="myTracnsactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<tx:advice id="txAdvice" transaction-manager="myTracnsactionManager">
		<tx:attributes>
			<!-- Specify transaction attributes for join points -->
			<tx:method name="add*" isolation="DEFAULT" propagation="REQUIRED"/>
			<tx:method name="buyStock" isolation="DEFAULT" propagation="REQUIRED" rollback-for="BuyStockException"/>
		</tx:attributes>
	</tx:advice>
	
	<aop:config>
		<!-- Point-of-entry configuration -->
		<aop:pointcut expression="execution(* *..service.*.*(..))" id="point"/>
		<aop:advisor advice-ref="txAdvice" pointcut-ref="point"/>
	</aop:config>

Miscellany

  1. The concept of transaction attributes, transaction attributes are usually composed of transaction propagation behavior, transaction isolation level, transaction timeout value and transaction read-only flag. These properties can be specified using @Transactional.
  2. The underlying principle: Spring transactions are actually Spring AOP. The underlying layer creates dynamic proxy objects and encapsulates open transactions and transaction rollback operations at the beginning and end of the code. It should be clearer to use JDBC native code, which is shown in the proxy commit and rollback. Then a lot of try catch.
  3. Add @Transactional before the service class to declare that all methods of this service require transaction management. Each business method opens a transaction at the beginning. Or on the service layer method, @Transactional can only be applied to the public method. For other non-public methods, if @Transactional is marked, it will not report errors, but the method has no transactional function. __________

Posted by raydenl on Tue, 14 May 2019 07:16:06 -0700