Spring Recognition - Services

参考文章:
1):https://blog.csdn.net/CHINACR07/article/details/78817449
2):https://blog.csdn.net/qq_38921377/article/details/72784494
3):
https://blog.csdn.net/feng20092009/article/details/70158964
4):
https://blog.csdn.net/qq_35069223/article/details/81166338

First, what is a transaction (transaction)

  1. The basic concept of a transaction of
    affairs is the application of a series of strict operation, all operations must be completed successfully, as long as there is a step fails, it will undo all the changes, that is, either all succeed, or all fail.

  2. spring underlying database transaction management mechanism based on its own transaction.

3. The four ACID properties of a transaction

1) Atomicity (Atomicity)
all operations of the entire transaction is not subdivided atomic units, either all the operations in the transaction are executed successfully, or have failed

2) Consistency (Consistency)
when the transaction is executed, if an error occurs, you should change back to its original state, consistent

3) Isolation (Isolation)
Isolation means in the concurrent operation, a different transaction should be isolated from each other, independently of each other.

4) Persistent (Durability)
Once the transaction is submitted successfully, all data operations in the transaction must be saved to the database persist, even after the transaction is committed, the database crashes, the database is restarted, it must be ensured through a certain mechanism Data recovery.

Second, the propagation behavior of the database

Transaction propagation behavior is when multiple transactions method calls, how to define a transaction between the method of propagation, spring defines the following seven propagation behavior

1.propagation_requierd: If no transaction creates a new transaction, if there is a transaction, added to this transaction, which is spring selected by default.

2.propagation_supports: support for the current transaction, if there is no current transaction, it will run in non-transactional method.

3) propagation_mandatory: Use the current transaction, if there is no current transaction, throw an exception (mandatory: mandatory)

4): propagation_required_new: New Transaction, if the current transaction, the current transaction pending.

5): propagation_not_support: non-transactional operations to perform a method, currently exists transaction, the pending transaction put.

6): propagation_never: performing an operation to a non-transactional way, if the current transaction exists, an exception is thrown

7): propagation_nested: if the current transaction is present, is performed in a nested transaction, if no transaction is performed with the operation similar propagation_required (nested nested)

Third, the operation may bring side effects of concurrent data

  1. Dirty read: also known as invalid data readout, a transaction reads data another transaction has not been submitted, it is called a dirty read.

eg: for example, I use the micro-channel pay a sum of money, but I withdrew halfway, the database has modified his data, database data read is dirty.

Solution, the database transaction isolation level is adjusted to READ_COMMITTED

  1. Non-repeatable read: a first current transaction carried out a data read, this time into the affairs b modify the data, when a transaction has not been completed, the data is read again to modify the data transaction b successful, resulting inTwo read data does not match, it will take care of the non-repeatable read semantics

The solution: the database transaction isolation level is adjusted to REPEATABLE_READ

  1. Magic Reading: transaction has been checked upon insertion of the record does not exist, the data has been surprisingly found that the presence of the detected data acquired before general as ghosting. .

eg: Transaction A first condition index n data obtained according to how transaction B change than the M or N data which adds the M data symbol transaction A search condition, leading to the transaction A search found again and N + M the pieces of data, it creates phantom reads.

The solution: the database transaction isolation level is adjusted to SERIALIZABLE_READ

Fourth, the transaction isolation level (the case of prevention above):

  1. read uncommited: lowest transaction isolation level, allowing another transaction can see the data that uncommitted transactions. (Three kinds of side effects is not preventable)

  2. read commited: After a transaction is committed to ensure that can be read by another transaction, another transaction can not read the uncommitted transactions. (Prevents dirty reads)

  3. repeatable read: A transaction will not see data at the same time another transaction modified but not yet committed (rollback) of (preventable dirty reads and non-repeatable read)

  4. serializable: This isolation level is all transactions are executed in a queue, the order of execution order, rather than in parallel (three kinds of side effects can be avoided, but inefficient)

Fifth, several implementations spring transaction management (mainly about declarative management)

1): programmatic transaction management application based on pojo of it is the only choice, we need to call beginTransaction (), commit (), rollback () , and other related transaction management method in the code, this is the programmatic transaction management.
2): TransactionProxyFactoryBean based declarative transaction management
3): @Transactional based declarative transaction management
4): Configuring transaction-based Aspectj Aop

Examples

  1. First POJO formula (omitted get and set methods and constructors)
//账户对象
public class Account{
	private int accountid;
	private String name;
	private String balance;
}

//股票对象
public class Stock{
	private int stockid;
	private String name;
	private Integer count;
}
  1. Followed by Dao layer (mainly written accounts and stocks increase and update)

2.1) account terms

public interface AccountDao{
	void addAccount(String name,double money);
	void updateAccount(String name,double money,boolean isbuy);
}
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao{
	@Override
	public void addAcount(String name,double money){
		String sql="insert account(name,balance) value (?,?);"
		this,getjdbcTemplate().update(sql,name,money);
	}

	@Override
	public void updateAccount(String name,double money,boolean isbuy){
		String sql="update account set balance = balance +? where name=?";
		if(isbuy)
			sql="update account set balance=balance-?where name =?";
		this,getjdbcTemplate.update(sql,money,name);
	}
}

2.2) aspects of stock

public interface StockDao {
	
	void addStock(String sname,int count);
	
	void updateStock(String sname,int count,boolean isbuy);
 
}

public class StockDaoImpl extends JdbcDaoSupport implements StockDao {
 
	@Override
	public void addStock(String sname, int count) {
		String sql = "insert into stock(name,count) values(?,?)";
		this.getJdbcTemplate().update(sql,sname,count);
	}
 
	@Override
	public void updateStock(String sname, int count, boolean isbuy) {
		String sql = "update stock set count = count-? where name = ?";
		if(isbuy)
			sql = "update stock set count = count+? where name = ?";
		this.getJdbcTemplate().update(sql, count,sname);
	}
	
}

Key Service Layer

public interface BuyStockService {
 
	public void addAccount(String accountname, double money);
	
	public void addStock(String stockname, int amount);
	
	public void buyStock(String accountname, double money, String stockname, int amount) throws BuyStockException;
	
}

Emphasis

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);
	}

	@Override
	public void buystock(String accountname,double money,String stockname,int amount)throw BuyStockException{
		boolean isBuy = true;
		accountDao.updateAccount(accountname, money, isBuy);
		if(isBuy==true){
			throw new BuyStockException("购买股票发生异常");
		}
			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;
	}

}
  1. Custom exception class definition (inherited exception, to intercept all exceptions)
public class BuyStockException extends Exception {
 
	public BuyStockException() {
		super();
	}
 
	public BuyStockException(String message) {
		super(message);
	}
 
}

Configuration (focus)

  1. The first is based on TransctionProxyFactoryBean declarative transaction management.
<?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"/>
	
	<!-- 注册数据源 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>
	
	
	<!-- 事务管理器 -->
	
	<bean id="myTracnsactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<!-- 事务代理工厂 -->
	<!-- 生成事务代理对象 -->
	<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>
				<!-- 主要 key 是方法   
					ISOLATION_DEFAULT  事务的隔离级别
					PROPAGATION_REQUIRED  传播行为
				-->
				<prop key="add*">ISOLATION_DEFAULT,PROPAGATION_REQUIRED</prop>
				<!-- -Exception 表示发生指定异常回滚,+Exception 表示发生指定异常提交 -->
				<prop key="buyStock">ISOLATION_DEFAULT,PROPAGATION_REQUIRED,-BuyStockException</prop>
			</props>
		</property>
	</bean>
	
</beans>  

Test class (mainly call buystock method)

	public static void main(String[] args) {
		String resouce = "transaction/test2/applicationContext.xml";
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext(resouce);
		BuyStockService buyStockService =  (BuyStockService) applicationContext.getBean("serviceProxy");
 
//		buyStockService.openAccount("小郑", 5000);
		
//		buyStockService.openStock("知晓科技", 0);
		
		try {
			buyStockService.buyStock("小郑", 1000, "知晓科技", 100);
		} catch (BuyStockException e) {
			e.printStackTrace();
		}
		
	}

  1. ** Based on the declarative transaction management @Transactional (just like the century-interface and configuration files) **
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("购买股票发生异常");
		}
			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;
	}
	
}

	<context:property-placeholder location="classpath:jdbc.properties"/>
	
	<!-- 注册数据源 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>
	
	
	<!-- 事务管理器 -->
	<bean id="myTracnsactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<!-- 启用事务注解 -->
	<tx:annotation-driven transaction-manager="myTracnsactionManager"/>

As can be seen, the use of @Transactional annotation Profiles are much simpler, annotation-driven transaction to transaction. It has a flaw that he will put all of the connection points are woven into the transaction as cut points inside, apparently only need buyStock () method can be woven into the transaction. Let's look at the last one implementation, it can precisely woven into the specified connection point

  1. Based Aspectj AOP configuration transaction (otherwise identical with the first approach, but the configuration information needs to be changed)
	<context:property-placeholder location="classpath:jdbc.properties"/>
	
	<!-- 注册数据源 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>
	
	
	<!-- 事务管理器 -->
	<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>
			<!-- 为连接点指定事务属性 -->
			<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>
		<!-- 切入点配置 -->
		<aop:pointcut expression="execution(* *..service.*.*(..))" id="point"/>
		<aop:advisor advice-ref="txAdvice" pointcut-ref="point"/>
	</aop:config>

Published 36 original articles · won praise 11 · views 10000 +

Guess you like

Origin blog.csdn.net/s_xchenzejian/article/details/100759729