Spring-事务的管理

事务管理

数据库事务(Database Transaction),是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。事务处理可以确保非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。通过将一组相关操作组合为一个要么全部成功要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠。一个逻辑工作单元要成为事务,必须满足所谓的ACID(原子性、一致性、隔离性和持久性)属性。事务是数据库运行中的逻辑工作单位,由DBMS的事务管理子系统负责事务的处理。

ACID:

原子性(Atomicity):事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。
一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态的含义是数据库中的数据应满足完整性约束。
隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行。
持久性(Durability):已被提交的事务对数据库的修改应该永久保存在数据库中。

DEMO:事务

package com.sxt.test;
public class Test {
	private String driverClassName = "com.mysql.jdbc.Driver";
	private String password = "tang123";
	private String userName = "root";
	private String url = "jdbc:mysql://localhost:3306/login?characterEncoding=utf-8";
	private Connection conn;

	/**
	 * 事务:保证多个DML操作要么同时成功要么同时失败
	 * 
	 * 不满足事务的情况
	 * @throws Exception
	 */
	@org.junit.Test
	public void test() throws Exception {
		Class.forName(driverClassName);
		conn = DriverManager.getConnection(url, userName, password);
		String sql1 = "insert into t_user(username,password)1values('a3','123')";
		Statement s = conn.createStatement();
		s.executeUpdate(sql1);
		String sql2 = "insert into t_user(username,password)values('a4','1234')";
		s.executeUpdate(sql2);
		s.close();
		conn.close();
	}
	
	/**
	 * 事务:保证多个DML操作要么同时成功要么同时失败
	 * 
	 * 满足事务的情况
	 * @throws Exception
	 */
	public void test1() throws Exception {
		Class.forName(driverClassName);
		conn = DriverManager.getConnection(url, userName, password);
		// 将自动提交关闭
		conn.setAutoCommit(false);
		Statement s = null;
		try {
			String sql1 = "insert into t_user(username,password)values('a4','123')";
			s = conn.createStatement();
			s.executeUpdate(sql1);
			String sql2 = "insert into t_user(username,password)values('a5','1234')";
			s.executeUpdate(sql2);
			// 提交数据
			conn.commit();
		}catch(Exception e){
			// 抛异常 回滚
			conn.rollback();
		} finally {
			s.close();
			conn.close();
		}
	}
}

实现:
在这里插入图片描述

AOP 代理模式:

在这里插入图片描述

Dao:

package com.sxt.dao;
import java.sql.Connection;
public interface IUserDao {
	public void insert(Connection conn) throws Exception;
	public void update(Connection conn)throws Exception;
	public void delete(Connection conn)throws Exception;
}

DaoImpl:

package com.sxt.dao.impl;
import java.sql.Connection;
import java.sql.Statement;
import com.sxt.dao.IUserDao;
public class UserDaoImpl implements IUserDao {
	private String sql;
	@Override
	public void insert(Connection conn) throws Exception {
		sql="insert into t_user(username,password)values()";
		Statement s=conn.createStatement();
		s.executeUpdate(sql);
	}
	@Override
	public void update(Connection conn) throws Exception{
		sql = "update t_user set username='aaa',password='bbb' where id = 11 ";
		Statement s = conn.createStatement();
		s.executeUpdate(sql);	
	}
	@Override
	public void delete(Connection conn) throws Exception{
		sql = "delete from t_user where id = 10";
		Statement s = conn.createStatement();
		s.executeUpdate(sql);
	}
}

Service

package com.sxt.service;
public interface IUserService {
	public void dml() throws Exception;
}

ServiceImpl

package com.sxt.service;
import java.sql.Connection;
import com.sxt.dao.IUserDao;
import com.sxt.dao.impl.UserDaoImpl;
public class UserServiceImpl implements IUserService {
	private Connection conn;
	public UserServiceImpl(Connection conn) {
		super();
		this.conn = conn;
	}
	private IUserDao dao = new UserDaoImpl();
	public void dml() throws Exception{
			dao.insert(conn);
			dao.update(conn);
	}
}

代理

package com.sxt.test;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DriverManager;

import org.junit.Before;
import org.junit.Test;

import com.sxt.service.IUserService;
import com.sxt.service.UserServiceImpl;

public class test {

	private String driverClassName = "com.mysql.jdbc.Driver";
	private String password = "tang123";
	private String userName = "root";
	private String url = "jdbc:mysql://localhost:3306/login?characterEncoding=utf-8";
	private Connection conn;
	@Before
	public void before() throws Exception {
		Class.forName(driverClassName);
		conn = DriverManager.getConnection(url, userName, password);
	}

	/**
	 * 事务:保证多个DML操作要么同时成功要么同时失败
	 * 
	 * 不满足事务的情况
	 * 
	 * @throws Exception
	 */
	@Test
	public void test() throws Exception {
		// 目标类
		IUserService target = new UserServiceImpl(conn);
		// 获取代理类
		IUserService proxy = (IUserService) Proxy.newProxyInstance(target.getClass().getClassLoader(),
				target.getClass().getInterfaces(), new InvocationHandler() {

					@Override
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						Object object = null;
						conn.setAutoCommit(false);
						try {
							object = method.invoke(target, args);
							conn.commit();
						} catch (Exception e) {
							// TODO: handle exception
							System.out.println("出现异常...回滚撤销");
							conn.rollback();
						} finally {
							conn.close();
						}
						return object;
					}
				});
		proxy.dml();

	}
}

实现:

在这里插入图片描述

配置xml文件的方式:

在这里插入图片描述

pojo:

package com.sxt.pojo;

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 query1();
	public void query2();
}

DaoImpl:

package com.sxt.dao.impl;

import java.util.List;

import javax.annotation.Resource;

import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import com.sxt.dao.UserDao;
import com.sxt.pojo.User;
@Repository
public class UserDaoImpl implements UserDao {
	@Resource
	private JdbcTemplate template;
	
	
	@Override
	public void add() {
		String sql="insert into t_user(username,password)values(?,?)";
		int i=template.update(sql,"tang","1234");
		System.out.println("影响的行数"+i);
	}

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

	}

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

	}

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

	@Override
	public void query2() {
		String sql="";
		int i=template.update(sql);
		System.out.println("影响的行数"+i);

	}

}

Service:

package com.sxt.service;

public interface IUserService {
	public void fun1();
}

ServiceImpl:

package com.sxt.service;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.sxt.dao.UserDao;

@Service
public class UserServiceImpl implements IUserService {


	@Resource
	private UserDao dao;

	@Override
	public void fun1() {
		dao.add();
		dao.update();
	}


}

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/login?characterEncoding=utf-8" />
		<property name="username" value="root" />
		<property name="password" value="tang123" />
	</bean>


	<!-- 配置JdbcTemplate -->
	<bean class="org.springframework.jdbc.core.JdbcTemplate" id="template">
		<!-- 构造注入关联数据源 -->
		<constructor-arg ref="dataSource"/>
	</bean>
	
	<!-- 配置事务 -->
	<!-- 配置事务管理器 -->
	<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="dataSourceTransactionManager">
		<!-- 关联数据源 -->
		<property name="dataSource" ref="dataSource"/>
	</bean>
	<!-- 配置事务的行为 -->
	<tx:advice id="txAdvice" 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="myPointcut"/>
		<aop:advisor advice-ref="txAdvice" pointcut-ref="myPointcut"/>
	</aop:config>
</beans>

测试:

在这里插入图片描述

基于注解的方式:

修改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/login?characterEncoding=utf-8" />
		<property name="username" value="root" />
		<property name="password" value="tang123" />
	</bean>


	<!-- 配置JdbcTemplate -->
	<bean class="org.springframework.jdbc.core.JdbcTemplate" id="template">
		<!-- 构造注入关联数据源 -->
		<constructor-arg ref="dataSource"/>
	</bean>
	
	<!-- 配置事务 -->
	<!-- 配置事务管理器 -->
	<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
		<!-- 关联数据源 -->
		<property name="dataSource" ref="dataSource"/>
	</bean> 
	<!-- 开启注释事务 -->
	<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>

修改ServiceImpl:

在这里插入图片描述

实现:

在这里插入图片描述

总结:

好处:
简单、灵活。
坏处:
跟业务的耦合性加强了

猜你喜欢

转载自blog.csdn.net/weixin_44502804/article/details/89407587