Java Interview Tutorial (Java Learning Guide) : github.com/Snailclimb/…

History review: Probably the most beautiful explanation of Spring transaction management

Spring Transaction Management

Spring supports transaction management in two ways:

  • Programmatic Transaction management: Manually managing transactions through the Transaction Template, which is rarely used in practice.
  • Use XML to configure declarative transactions: Recommended (least intrusive code) and actually implemented via AOP

There are four ways to implement declarative transactions:

  1. Declarative transactions based on TransactionInterceptor: The foundation of Spring declarative transactions, this approach is also not generally recommended, but as before, it is very useful for understanding Spring declarative transactions.

  2. Based on TransactionProxyFactoryBean declarative transaction: improved version of the first way, simplified configuration file writing, it is early Spring recommended way of declarative transaction management, but in Spring 2.0 is no longer recommended.

  3. Declarative transaction management based on < TX > and < AOP > namespaces: the current recommended approach is closely combined with Spring AOP, which can make full use of the powerful support of pointcut expressions, making transaction management more flexible.

  4. Fully annotated with @Transactional: Simplifies declarative transaction management to the extreme. A developer can implement transaction management by simply adding a line in the configuration file to enable the configuration of the associated post-processing beans, and then using @Transactional to specify transaction rules on the method or class that requires transaction management.

What we’re going to do today is use programmatic and AspectJ-based declarative and annotation-based transactions to implement a popular transfer business.

To return to the idea of this case, we add an error statement between the two transfers (for unexpected situations such as bank power outages). If the two transfers fail at this time, the transaction is correctly configured, otherwise, the transaction is incorrectly configured.

Tasks you need to complete:

  • Use programmatic transaction management to complete transfer transactions
  • Use AspectJ-based declarative transaction management for transfer transactions
  • Use fully annotated transaction management based on @Transactional to complete transfers

Remark:

The following code was written a long time ago when I just learned Sping and did not touch Maven, so I used the original way of adding JARS. If you use Maven, you can add your Maven dependencies by yourself. If you do not use Maven, you can directly use the jar package I provided below.

Jar package address: Link: pan.baidu.com/s/1tqy-mVKx… Password: nid0

Project Structure:

Development tools:

Myeclipse2017

SQL:


create table `account` (
	`username` varchar (99),
	`salary` int (11));insert into `account` (`username`.`salary`) values('wang'.'3000');
insert into `account` (`username`.`salary`) values('小马'.'3000');

Copy the code

(1) Programmatic transaction management

Note: You can verify that transaction management is configured correctly by adding/removing the int I = 10/0 statement in the accountMoney() method.

OrdersDao. Java layer (Dao)

package cn.itcast.dao;

import org.springframework.jdbc.core.JdbcTemplate;

public class OrdersDao {
	// Inject the jdbcTemplate template object
	private JdbcTemplate jdbcTemplate;

	public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}

	// Methods that operate on data do not include business operations
	/** * Xiao Wang's way to get less money */
	public void reduceMoney(a) {
		String sql = "update account set salary=salary-? where username=?";
		jdbcTemplate.update(sql, 1000."Wang");
	}

	/** ** Pony more money method */
	public void addMoney(a) {
		String sql = "update account set salary=salary+? where username=?";
		jdbcTemplate.update(sql, 1000."Pony"); }}Copy the code

Ordersservice.java (Business Logic layer)

package cn.itcast.service;

import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;

import cn.itcast.dao.OrdersDao;

public class OrdersService {
	// Inject Dao layer objects
	private OrdersDao ordersDao;

	public void setOrdersDao(OrdersDao ordersDao) {
		this.ordersDao = ordersDao;
	}

	// Inject the TransactionTemplate object
	private TransactionTemplate transactionTemplate;

	public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
		this.transactionTemplate = transactionTemplate;
	}

	// Call dao's methods
	// Write the transfer business
	public void accountMoney(a) {
		transactionTemplate.execute(new TransactionCallback<Object>() {

			@Override
			public Object doInTransaction(TransactionStatus status) {
				Object result = null;
				try {
					// Ponies 1000
					ordersDao.addMoney();
					// add an exception like the following int
					// I =10/0 ; Result: Xiao Ma's account is 1000 more and Xiao Wang's account has no less money
					// The solution is to roll back the transaction after an exception occurs
					int i = 10 / 0;// The exception has been resolved after the transaction management configuration
					// Xiao Wang is less than 1000
					ordersDao.reduceMoney();
				} catch (Exception e) {
					status.setRollbackOnly();
					result = false;
					System.out.println("Transfer Error!");
				}

				returnresult; }}); }}Copy the code

Testservice.java (Test method)

package cn.itcast.service;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestService {
	@Test
	public void testAdd(a) {
		ApplicationContext context = new ClassPathXmlApplicationContext(
				"beans.xml");
		OrdersService userService = (OrdersService) context
				.getBean("ordersService"); userService.accountMoney(); }}Copy the code

Configuration file:

<? 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: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-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd "> <! - configuration c3po connection pool - > < bean id = "dataSource" class = "boPooledDataSource com.mchange.v2.c3p0.Com" > <! <property name="driverClass" value="com.mysql.jdbc.Driver"></property> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/wangyiyun"></property> <property name="user" value="root"></property> <property name="password" value="153963"></property> </bean> <! Programmatic transaction Management --> <! - configuration transaction manager - > < bean id = "dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <! DataSource --> < dataSource name="dataSource" ></property> </bean> <! - configuration transaction manager template - > < bean id = "transactionTemplate" class = "org. Springframework. Transaction. Support. TransactionTemplate" > <! <property name="transactionManager" ref="dataSourceTransactionManager"></property> </bean> <! Generated objects and attributes inject - > < bean id = "ordersService" class = "cn. Itcast. Service. OrdersService" > < property name = "ordersDao" ref="ordersDao"></property> <! <property name="transactionTemplate" ></property> </bean> <bean id="ordersDao"  class="cn.itcast.dao.OrdersDao"> <property name="jdbcTemplate" ref="jdbcTemplate"></property> </bean> <! - JDBC template objects - > < bean id = "jdbcTemplate" class = "org. Springframework. JDBC. Core. JdbcTemplate" > < property name = "dataSource" ref="dataSource"></property> </bean> </beans>Copy the code

(2) AspectJ-based declarative transaction management

Ordersservice.java (Business Logic layer)

package cn.itcast.service;

import cn.itcast.dao.OrdersDao;

public class OrdersService {
	private OrdersDao ordersDao;

	public void setOrdersDao(OrdersDao ordersDao) {
		this.ordersDao = ordersDao;
	}

	// Call dao's methods
	// Write the transfer business
	public void accountMoney(a) {
		// Ponies 1000
		ordersDao.addMoney();
		Int I =10/0 int I =10/0 ; Result: Xiao Ma's account is 1000 more and Xiao Wang's account has no less money
		// The solution is to roll back the transaction after an exception occurs
		int i = 10 / 0;// The exception has been resolved after the transaction management configuration
		// Xiao Wang is less than 1000ordersDao.reduceMoney(); }}Copy the code

Configuration file:

	<! C3po connection pool -->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<! Insert property values -->
		<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
		<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/wangyiyun"></property>
		<property name="user" value="root"></property>
		<property name="password" value="153963"></property>
	</bean>
	<! Step 1: Configure the transaction manager
	<bean id="dataSourceTransactionManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<! DataSource -->
		<property name="dataSource" ref="dataSource"></property>
	</bean>

	<! Step 2: Configure transaction enhancement -->
	<tx:advice id="txadvice" transaction-manager="dataSourceTransactionManager">
		<! -- Do transaction operations -->
		<tx:attributes>
			<! Set method matching rules for transaction operations -->
			<! -- All methods at the beginning of account -->
	        <! Propagation: transaction propagation behavior; Isolation: transaction isolation level; Read-only: indicates whether it is read-only. Rollback-for: rollback when those exceptions occur timeout: transaction expiration time -->
			<tx:method name="account*" propagation="REQUIRED"
				isolation="DEFAULT" read-only="false" rollback-for="" timeout="1" />
		</tx:attributes>
	</tx:advice>

	<! Step 3: Configure facets facets are the process of applying enhancements to methods.
	<aop:config>
		<! -- entry point -->
		<aop:pointcut expression="execution(* cn.itcast.service.OrdersService.*(..) )"
			id="pointcut1" />
		<! - section - >
		<aop:advisor advice-ref="txadvice" pointcut-ref="pointcut1" />
	</aop:config>


	<! Object generation and property injection -->
	<bean id="ordersService" class="cn.itcast.service.OrdersService">
		<property name="ordersDao" ref="ordersDao"></property>
	</bean>
	<bean id="ordersDao" class="cn.itcast.dao.OrdersDao">
		<property name="jdbcTemplate" ref="jdbcTemplate"></property>
	</bean>
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
Copy the code

(3) Annotation-based approach

Ordersservice.java (Business Logic layer)

package cn.itcast.service;

import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import cn.itcast.dao.OrdersDao;

@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, readOnly = false, timeout = -1)
public class OrdersService {
	private OrdersDao ordersDao;

	public void setOrdersDao(OrdersDao ordersDao) {
		this.ordersDao = ordersDao;
	}

	// Call dao's methods
	// Write the transfer business
	public void accountMoney(a) {
		// Ponies 1000
		ordersDao.addMoney();
		Int I =10/0 int I =10/0 ; Result: Xiao Ma's account is 1000 more and Xiao Wang's account has no less money
		// The solution is to roll back the transaction after an exception occurs
		// int i = 10 / 0; // The exception has been resolved after the transaction management configuration
		// Xiao Wang is less than 1000ordersDao.reduceMoney(); }}Copy the code

Configuration file:

	<! C3po connection pool -->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<! Insert property values -->
		<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
		<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/wangyiyun"></property>
		<property name="user" value="root"></property>
		<property name="password" value="153963"></property>
	</bean>
	<! -- Step 1: Configure transaction manager (same as configuration file)-->
	<bean id="dataSourceTransactionManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<! DataSource -->
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	<! Step 2: Enable transaction annotations -->
	<tx:annotation-driven transaction-manager="dataSourceTransactionManager" />
	<! Step 3 add a comment to the class on which the method belongs -->
	
	
	<! Object generation and property injection -->
	<bean id="ordersService" class="cn.itcast.service.OrdersService">
		<property name="ordersDao" ref="ordersDao"></property>
	</bean>
	<bean id="ordersDao" class="cn.itcast.dao.OrdersDao">
		<property name="jdbcTemplate" ref="jdbcTemplate"></property>
	</bean>
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
Copy the code

Welcome to my wechat official account: “Java Interview Clearance Manual “(a warm wechat official account, looking forward to common progress with you ~~~ adhere to the original, share beautiful articles, share a variety of Java learning resources) :