使用Spring管理事务

1 篇文章 0 订阅

6.1 理解事务管理

任何处理数据的系统都必须保证数据的完整性、事务为与数据相关的操作定义了一个边界,并将他们组合在一起,以便这些操作的最终结果不会使底层数据出于不一致的状态。

具有的特性:原子性 事务在数据上有多个操作而且每个操作都必须成功,否则进行回滚。一致性 一个活动事务结束后底层事务必须处于一致状态。 隔离性 定义了保护未提交的数据免受其他并发事务的影响。 持久性 接收到一个成功的信息提交时,系统就具有了持久性。

package com.tzg.ch601;

public interface AccountServer {

	public void transferMoney(long sourceAccountId,long targetAccountId,double amount);
}
package com.tzg.ch601;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

import com.mysql.jdbc.Connection;
import com.mysql.jdbc.Driver;

public class AccountServerJdbcTxImpl implements AccountServer {

	@Override
	public void transferMoney(long sourceAccountId, long targetAccountId,
			double amount) {
		 Connection connection = null;
		 System.out.println("开始。。。。。。。。。");
		 try {
			 System.out.println("开启事务。。。。。。。。。");
			 //加载驱动
			DriverManager.registerDriver(new Driver());
			//取得连接DriverManager.getConnection();
			connection=(Connection) DriverManager.getConnection("jdbc:mysql://localhost:3306/num","root","123456");
			//调用connection.setAutoCommit(false)来标记使用JDBC API定义的事务边界起点,来引起一个新的事务的开始。
			connection.setAutoCommit(false); 
			//取得接口的声明
			Statement statement = connection.createStatement();
			statement.executeUpdate("update account set balance = balance - "+amount+ "where id= "+sourceAccountId);
			statement.executeUpdate("update account set balance = balance + "+amount+ "where id= "+targetAccountId);
			//事务划分成功终止
			connection.commit();
		 } catch (SQLException e) {
			try {
				//处理的数据中如果发现了错误,用connection.rollback()回滚告诉jdbc抛弃目前为止所做的任何更改。
				System.out.println("发现错误。。。。。。。");
				connection.rollback();
				
			} catch (SQLException e1) {
				System.out.println("数据库操作失败");
			}
			
			throw new RuntimeException(e);
		}
		
		 
		 
	}

}
package com.tzg.ch601;

public class Main {

	public static void main(String[] args) {
		AccountServer accountServer=new AccountServerJdbcTxImpl();
	    accountServer.transferMoney(100L, 101L, 6.0d);	
	    System.out.println("运行结束。。。。。。。。。。。");
	}
}

项目结构:

  

6.2 spring 的事务抽象模型

Spring的事务抽象模型基于PlatformTransactionManager接口并且存在不同的具体实现,而且每种实现都与一个特定的访问技术相对应,个人要确定好是使用的那一个技术。默认的情况下为transactionManager

6.2.1 本地事务与全局事务

本地应用程序使用单一的数据库,切事务仅控制在该单一的数据库上执行的DML操作。全局事务则意味着分布式事务管理。在一个事务中可能涉及到多个数据库。

6.2.2 PlatformTransactionManager 实现

6.2.3Spring 的抽象事务模型的优点

能够在相同的应用平台中使用不同的数据访问技术、可以同时使用声明式和编程式访问模型。本地事务和全局事务很容易转换。

6.3 使用Spring进行声明式事务管理

事务管理是一个横切关注点,而横切关注点最好使用面向方面编程来处理。

实例 spring中启动声明事务管理

package com.tzg.ch602;

public interface AccountServer {

	public void transferMoney(long sourceAccountId,long targetAccountId,double amount);
}
package com.tzg.ch602;

import java.sql.SQLException;
import java.sql.Statement;

import javax.sql.DataSource;

import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.transaction.annotation.Transactional;

import com.mysql.jdbc.Connection;

public class AccountServerImpWithSpring implements AccountServer {
 
	private DataSource dataSource;
	
	
	public void setDataSource(DataSource dataSource) {
		this.dataSource = dataSource;
	}


	@Transactional
	public void transferMoney(long sourceAccountId, long targetAccountId,
			double amount) {
		Connection connection=(Connection) DataSourceUtils.getConnection(dataSource);
        try {
			Statement statement =connection.createStatement();
			statement.executeUpdate("update account set balance = balance - "+amount+ "where id= "+sourceAccountId);
			statement.executeUpdate("update account set balance = balance + "+amount+ "where id= "+targetAccountId);
	        
		} catch (SQLException e) {
			// TODO Auto-generated catch block
		throw new RuntimeException();
		}finally{
			DataSourceUtils.releaseConnection(connection, dataSource);
		}
        
	}

}
package com.tzg.ch602;

import javax.sql.DataSource;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportResource;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
//激活了基于注解的事务管理
 @EnableTransactionManagement 
public class Ch6Configuration {
	  @Bean
	  public DataSource dataSource(){
		  DriverManagerDataSource dataSource = new DriverManagerDataSource();
		  dataSource.setDriverClassName("com.mysql.jdbc.Driver");
		  dataSource.setUrl("jdbc:mysql://localhost:3306/num");
		  dataSource.setUsername("root");
		  dataSource.setPassword("123456");
		  return dataSource;
	  }
	  @Bean
	  public PlatformTransactionManager transactionManager(){
		DataSourceTransactionManager transactionManager=new DataSourceTransactionManager();
		transactionManager.setDataSource(dataSource());
		return transactionManager;
	  }
	  @Bean
	  public AccountServer accountServer(){
		  AccountServerImpWithSpring bean=new AccountServerImpWithSpring();
		  bean.setDataSource(dataSource());
		  return bean;
	  }
	  
}
package com.tzg.ch602;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {

	private static AnnotationConfigApplicationContext configApplicationContext;

	public static void main(String[] args) {
	configApplicationContext = new AnnotationConfigApplicationContext(Ch6Configuration.class);
	AccountServer accountServer=configApplicationContext.getBean(AccountServer.class);
	accountServer.transferMoney(100L, 101L, 2.0d);
	}

}

6.3.1 将服务层与数据访问层进行分离

package com.tzg.ch402;

import org.springframework.transaction.annotation.Transactional;

public class AccountServiceImpl implements AccountServer {

	private AccountDao accountdao;
	
	public void setAccountdao(AccountDao accountdao) {
		this.accountdao = accountdao;
	}

   @Transactional /*(没有这个注解的是基于xml的)*/
   //标记服务类的transferMoney(..)方法,并实现该方法。注意其中要导入包aspectj.weaver.jar 包
	public void transferMoney(long sourceAccountId, long targetAccountId,
			double amount) {
		Account sourceAccount=accountdao.find(sourceAccountId);
		Account targetAccount=accountdao.find(targetAccountId);
		sourceAccount.setBalance(sourceAccount.getBalance()-amount);
		targetAccount.setBalance(targetAccount.getBalance()+amount);
        accountdao.update(sourceAccount);
        accountdao.update(targetAccount);
	}
}
package com.tzg.ch402;
import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportResource;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
//激活了基于注解的事务管理
@EnableTransactionManagement
@ImportResource("classpath:/beans-tx.xml")
@Import(Ch4Configuration.class)
public class Ch6Configuration {
	  @Bean
	  public DataSource dataSource(){
		  DriverManagerDataSource dataSource = new DriverManagerDataSource();
		  dataSource.setDriverClassName("com.mysql.jdbc.Driver");
		  dataSource.setUrl("jdbc:mysql://localhost:3306/num");
		  dataSource.setUsername("root");
		  dataSource.setPassword("123456");
		  return dataSource;
	  }
	  @Bean
	  public PlatformTransactionManager transactionManager(){
		DataSourceTransactionManager transactionManager=new DataSourceTransactionManager();
		transactionManager.setDataSource(dataSource());
		return transactionManager;
	  }
	  
	  @Bean
	  @Autowired//可以在创建方法期间将accountDao Bean作为一个方法输入参数传入到方法中。
	  public AccountServer accountServer(AccountDao accountDao){
		 AccountServiceImpl bean=new AccountServiceImpl();
		 bean.setAccountdao(accountDao);
		 return bean;
				 
	  }
	  
/*	  @Bean
	  public AccountServer accountServer(){
		  AccountServerImpWithSpring bean=new AccountServerImpWithSpring();
		  bean.setDataSource(dataSource());
		  return bean;
	  }
	  */
}

注意其中的依赖包

6.3.5 使用<tx:advice>进行声明事务管理

添加依赖

 <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.6.11</version>
        </dependency>

创建beans-tx.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:tx="http://www.springframework.org/schema/tx"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
        
	<tx:advice id="txAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			<tx:method name="*" propagation="REQUIRED" />
		</tx:attributes>
	</tx:advice>
	<aop:config>
		<aop:advisor advice-ref="txAdvice" pointcut="bean(accountService)" />
	</aop:config>
</beans>

删除出AccountServiceImpl类中的@Transaction注解。添加

@Configuration
//激活了基于注解的事务管理
@ImportResource("classpath:/beans-tx.xml")
@Import(Ch4Configuration.class)

6.4 使用Spring进行编程式事务管理

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值