使用Spring框架下的完成对事务的操作

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_28194001/article/details/78823116

上一章节,我使用了Spring的JDBCTemplate完成了对数据库的操作。但是在一般的情况下,我们对数据库操作时都需要进行事务管理的操作,防止数据库中的数据出现读取到错误提交的数据,如A转账给B,A扣款了,B没有收到款(脏读)等问题。

事务需要满足4大特性:

    1. 原子性  完成对数据的修改 要么一起执行,要么一起不执行 强调整体
    2. 一致性  存储的数据约束应该一致
    3. 隔离性  防止冲突 并发的事务是相互隔离 不互相影响的
    4. 持久性  确保已经提交的事务内容不丢失

涉及:Mysql5.7,Eclipse javaEE,Spring3.2,JDK1.7

此处使用的练习案例是转账。实现A对B进行转账,如果期间出现了异常则事务回滚。

首先,需要创建一个表 这里我们就只用到用户名和账内金额两个字段即可

CREATE TABLE `transfer` (
  `username` varchar(15) DEFAULT NULL,
  `money` int(10) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
insert into transfer (`username`, money) value ('pp', 10000);
insert into transfer (`username`, money) value ('qq', 10000);
 

在其中存储两个用户,设定账户都为10000。

 

在java中创建一个项目,导入相应的包(除了Spring必要包外 tx事务处理包,orm包,jdbc包,mysql驱动包,c3p0等)

Dao类

package com.hpp.dao;

public interface TransferDao {
	public void in(String inner, Integer money);
	public void out(String outer, Integer money);
}

Dao实现类
package com.hpp.dao.impl;

import org.springframework.jdbc.core.support.JdbcDaoSupport;

import com.hpp.dao.TransferDao;

//需要继承JdbcDaoSupport 其中有dataSource变量 在xml文件中注入数据源
public class TransferDaoImpl extends JdbcDaoSupport implements TransferDao{

	@Override
	public void in(String inner, Integer money) {
		this.getJdbcTemplate().update("update transfer set money=money-? where username=? ",
				money,inner);
	}

	@Override
	public void out(String outer, Integer money) {
		this.getJdbcTemplate().update("update transfer set money=money+? where username=? ",
				money,outer);
	}
}


Service类

package com.hpp.service;

public interface TransferService {
	void transfer(String outer, String inner, Integer money);
}
Service实现类
package com.hpp.service.impl;

import com.hpp.dao.TransferDao;
import com.hpp.service.TransferService;

public class TransferServiceImpl implements TransferService{

	private TransferDao transferDao;
	public void setTransferDao(TransferDao transferDao) {
		this.transferDao = transferDao;
	}
	
	@Override
	public void transfer(final String outer, final String inner, final Integer money) {
		transferDao.in(outer, money);
//		手动设置的异常
//		int i = 1/0;
		transferDao.out(inner, money);
	}
	
}

JdbcInfo.properties文件,此处用到xml文件加载数据库参数,让数据库参数可配置

jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql://127.0.0.1:3306/mydb
jdbc.user=root
jdbc.password=8469

Spring配置 applicationContext.xml

<?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:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       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/aop
       					   http://www.springframework.org/schema/aop/spring-aop.xsd
       					   http://www.springframework.org/schema/context 
       					   http://www.springframework.org/schema/context/spring-context.xsd
       					   http://www.springframework.org/schema/tx
       					   http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
	<!-- 读取properties文件 -->
	<context:property-placeholder location="classpath:com/hpp/properties/JdbcInfo.properties"/>
	<!-- 加载数据源 -->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="driverClass" value="${jdbc.driverClass}"></property>
		<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
		<property name="user" value="${jdbc.user}"></property>
		<property name="password" value="${jdbc.password}"></property>
	</bean>
	<bean id="transferDao" class="com.hpp.dao.impl.TransferDaoImpl">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<bean id="transferService" class="com.hpp.service.impl.TransferServiceImpl">
		<property name="transferDao" ref="transferDao"></property>
	</bean>
	
	<!-- 事务管理器 -->
	<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	<!-- 事务通知 -->
	<tx:advice id="txAdvice" transaction-manager="txManager">
		<tx:attributes>
			<!-- 
				对指定方法进行事务管理
				propagation 取值:
				REQUIRED为默认值 支持当前事务,A如果有事务,B将使用该事务;如果A没有事务,B将创建一个新的事务
			-->            
			<tx:method name="transfer" propagation="REQUIRED" isolation="DEFAULT"/>
		</tx:attributes>
	</tx:advice>
	<!-- AOP编程 -->
	<aop:config>
		<aop:advisor advice-ref="txAdvice" pointcut="execution(* com.hpp.service..*.*(..))"/>
	</aop:config>
</beans>	<tx:advice id="txAdvice" transaction-manager="txManager">
		<tx:attributes>
			<!-- 
				对指定方法进行事务管理
				propagation 取值:
				REQUIRED为默认值 支持当前事务,A如果有事务,B将使用该事务;如果A没有事务,B将创建一个新的事务
			-->            
			<tx:method name="transfer" propagation="REQUIRED" isolation="DEFAULT"/>
		</tx:attributes>
	</tx:advice>
	<!-- AOP编程 -->
	<aop:config>
		<aop:advisor advice-ref="txAdvice" pointcut="execution(* com.hpp.service..*.*(..))"/>
	</aop:config>
</beans>

测试类

package com.hpp;

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

import com.hpp.service.TransferService;

public class TestTransfer {
	@Test
	public void test1() {
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		TransferService transferService = (TransferService) applicationContext.getBean("transferService");
		transferService.transfer("pp", "qq", 1000);
	}
}

当没有异常发生时,转账操作事务可以正常提交,当其中出现了异常,事务会回滚。此处我使用整数除以零来形成一个异常进行测试。

刚接触内容较浅显,主要是想让自己在将来使用的时候有这方面的印象,因此记下此学习记录。如有错误以及需要改进的地方 劳烦指出。

猜你喜欢

转载自blog.csdn.net/qq_28194001/article/details/78823116