Spring之事务管理

事务管理

事务的认识

数据库事务,是指作为单个工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。事务管理可以确保除非事务性单元内地所有操作都成功完成,否则不会永久更新面向数据地资源。

事务具备ACID四种特性,ACID是Atomic(原子性)、Consistency(一致性)、Isolation(隔离性)和Durability(持久性)的英文缩写。

①、原子性(Atomicity):事务是一个原子操作,由一系列动作组成。事务的原子性确保动作要么全部完成,要么完全不起作用。

②、一致性(Consistency):一旦事务完成(不管成功还是失败),系统必须确保它所建模的业务处于一致的状态,而不会是部分完成部分失败。在现实中的数据不应该被破坏。

③、隔离性(Isolation):可能有许多事务会同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏。

④、持久性(Durability):一旦事务完成,无论发生什么系统错误,它的结果都不应该受到影响,这样就能从任何系统崩溃中恢复过来。通常情况下,事务的结果被写到持久化存储器中。

事务的隔离级别

(1)read uncommited:是最低的事务隔离级别,它允许另外一个事务可以看到这个事务未提交的数据。
(2)read commited:保证一个事物提交后才能被另外一个事务读取。另外一个事务不能读取该事物未提交的数据。
(3)repeatable read:这种事务隔离级别可以防止脏读,不可重复读。但是可能会出现幻象读。它除了保证一个事务不能被另外一个事务读取未提交的数据之外还避免了以下情况产生(不可重复读)。
(4)serializable:这是花费最高代价但最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读之外,还避免了幻象读
(5)脏读、不可重复读、幻象读概念说明:
a.脏读:指当一个事务正字访问数据,并且对数据进行了修改,而这种数据还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。因为这个数据还没有提交那么另外一个事务读取到的这个数据我们称之为脏数据。依据脏数据所做的操作肯能是不正确的。
b.不可重复读:指在一个事务内,多次读同一数据。在这个事务还没有执行结束,另外一个事务也访问该同一数据,那么在第一个事务中的两次读取数据之间,由于第二个事务的修改第一个事务两次读到的数据可能是不一样的,这样就发生了在一个事物内两次连续读到的数据是不一样的,这种情况被称为是不可重复读。
c.幻象读:一个事务先后读取一个范围的记录,但两次读取的纪录数不同,我们称之为幻象读(两次执行同一条 select 语句会出现不同的结果,第二次读会增加一数据行,并没有说这两次执行是在同一个事务中)

案例演示(为了方便使用注解)

bean层

package com.sxt.bean;

public class User {

	private int id;
	
	private String username;
	
	private String password;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	@Override
	public String toString() {
		return "User [id=" + id + ", username=" + username + ", password=" + password + "]";
	}
	
	
}

Dao层及其实现类

package com.sxt.dao;

public interface UserDao {
	public void add();
	public void update();
	public void delete();
	public void query();
}

package com.sxt.dao.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.stereotype.Repository;

import com.sxt.bean.User;
import com.sxt.dao.UserDao;
@Repository
public class UserDaoImpl implements UserDao {
	@Autowired
	private JdbcTemplate template;

	@Override
	public void add() {
		String sql = "insert t_user(username,password)values(?,?)";
		int i = template.update(sql,"aa","11");
		System.out.println("影响一行"+i);

	}

	@Override
	public void update() {
		String sql = "update t_user set username=?,password=? where id=?";
		int i = template.update(sql,"bb","22",2);
		System.out.println("影响一行"+i);

	}

	@Override
	public void delete() {
		String sql = "delete from t_user where id=?";
		int i = template.update(sql,2);
		System.out.println("影响一行"+i);

	}

	@Override
	public void query() {
		String sql = "select * from t_user";
		List<User> query = template.query(sql, new BeanPropertyRowMapper<User>(User.class));
		for (User user : query) {
			System.out.println(user);
		}
		
	}

}

Service层及其实现类

package com.sxt.service;

public interface UserService {
		public void fun();
}

package com.sxt.service.impl;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.sxt.dao.UserDao;
import com.sxt.service.UserService;
@Service
public class UserServiceImpl implements UserService{
		@Resource
		private UserDao dao;
	@Override
	public void fun() {
		dao.add();
		dao.delete();
		dao.update();
		dao.query();
		
	}

}

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: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.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
		<!-- 开启注解 -->
	<context:component-scan base-package="com.sxt.*"></context:component-scan>
	<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource">
			<!-- 设置注入 -->
			<property name="driverClassName" value="com.mysql.jdbc.Driver "/>
			<property name="url" value="jdbc:mysql://localhost:3306/pms?characterEncoding=utf-8"/>
			<property name="username" value="root"/>
			<property name="password" value="123456"/>
	</bean>
	<bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate">
		<constructor-arg ref="dataSource"/>
	</bean>
	<!-- 配置事务管理 -->
	<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="dataSourceTransactionManager">
			<property name="dataSource" ref="dataSource"></property>
	</bean>
	<!-- 配置事务方法 -->
	<tx:advice id="tx" transaction-manager="dataSourceTransactionManager">
			<tx:attributes>
				<tx:method name="fun*" propagation="REQUIRED"/>
			</tx:attributes>
	</tx:advice>
		<!-- 配置AOP -->
	<aop:config>
			<aop:pointcut expression="execution(* com.sxt.service.impl.*.*(..))" id="aop"/>
			<aop:advisor advice-ref="tx" pointcut-ref="aop"/>
	</aop:config>
</beans>

Spring之事务管理

测试调用

package com.sxt;

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


import com.sxt.service.UserService;
/**
 * 测试
 * @author Administrator
 *
 */
public class Test {
public static void main(String[] args) {
	ApplicationContext ac = new ClassPathXmlApplicationContext("application.xml");
	UserService bean = ac.getBean(UserService.class);
	bean.fun();
}
}

Spring之事务管理
Spring之事务管理

在Dao层实现类给出代码错误代码

Spring之事务管理

在测试运行

Spring之事务管理
Spring之事务管理

虽然结果显示影响一行但是数据库并没有添加删除,修改数据,事务管理保证了对这一系列的数据库增删查改要么同时成功,要么同时失败

使用注解方式

Dao层及其实现类和service层代码一样引用上面的

配置文件

<?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.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
		<!-- 开启注解 -->
	<context:component-scan base-package="com.sxt.*"></context:component-scan>
	<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource">
			<!-- 设置注入 -->
			<property name="driverClassName" value="com.mysql.jdbc.Driver "/>
			<property name="url" value="jdbc:mysql://localhost:3306/pms?characterEncoding=utf-8"/>
			<property name="username" value="root"/>
			<property name="password" value="123456"/>
	</bean>
	<bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate">
		<constructor-arg ref="dataSource"/>
	</bean>
	<!-- 配置事务管理 -->
	<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="dataSourceTransactionManager">
			<property name="dataSource" ref="dataSource"></property>
	</bean>
	<!-- 开启注解地方式 -->
	<tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>
</beans>

Spring之事务管理

service实现类

package com.sxt.service.impl;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.sxt.dao.UserDao;
import com.sxt.service.UserService;
@Service
public class UserServiceImpl implements UserService{
		@Resource
		private UserDao dao;
	@Transactional
	@Override
	public void fun() {
		dao.add();
		dao.delete();
		dao.update();
		dao.query();
		
	}

}

Spring之事务管理

测试

package com.sxt;

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


import com.sxt.service.UserService;

public class Test {
public static void main(String[] args) {
	ApplicationContext ac = new ClassPathXmlApplicationContext("application.xml");
	UserService bean = ac.getBean(UserService.class);
	bean.fun();
}
}

结果效果图附上