spring的简单入门(四)之事务

1.什么是事务

►事务管理是企业级应用程序开发中必不可少的技术,  用来确保数据的完整性和一致性.
►事务就是一系列的动作, 它们被当做一个单独的工作单元. 这些动作要么全部完成, 要么全部不起作用
►事务的四个关键属性(ACID)
§原子性(atomicity):事务是一个原子操作, 由一系列动作组成. 事务的原子性确保动作要么全部完成要么完全不起作用.
§一致性(consistency):一旦所有事务动作完成, 事务就被提交. 数据和资源就处于一种满足业务规则的一致性状态中.
§隔离性(isolation):可能有许多事务会同时处理相同的数据, 因此每个事物都应该与其他事务隔离开来, 防止数据损坏.
持久性(durability):一旦事务完成, 无论发生什么系统错误, 它的结果都不应该受到影响. 通常情况下, 事务的结果被写到持久化存储器中.

二.事务的传播性,简单的引用

创建maven项目,在pom.xml中加载架包

<project xmlns="http://maven.apache.org/POM/4.0.0" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>cn</groupId>
  <artifactId>spring</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <dependencies>
  <!-- 加载spring的包 -->
  	<dependency>
  		<groupId>org.springframework</groupId>
  		<artifactId>spring-context</artifactId>
  		<version>4.3.12.RELEASE</version>
  	</dependency>
  	
  	<dependency>
  		<groupId>aopalliance</groupId>
  		<artifactId>aopalliance</artifactId>
  		<version>1.0</version>
  	</dependency>
  	<dependency>
  		<groupId>aspectj</groupId>
  		<artifactId>aspectjweaver</artifactId>
  		<version>1.5.3</version>
  	</dependency>
  	<!-- 添加jdbc的架包 -->
  	<dependency>
  		<groupId>org.springframework</groupId>
  		<artifactId>spring-jdbc</artifactId>
  		<version>4.3.12.RELEASE</version>
  	</dependency>
  		<!-- 加载数据库的架包 -->
  	<dependency>
  		<groupId>mysql</groupId>
  		<artifactId>mysql-connector-java</artifactId>
  		<version>5.1.26</version>
  	</dependency>
  	<!-- 面向切面编程 -->
  	<dependency>
  		<groupId>org.springframework</groupId>
  		<artifactId>spring-aop</artifactId>
  		<version>4.3.12.RELEASE</version>
  	</dependency>
  	<dependency>
  		<groupId>org.springframework</groupId>
  		<artifactId>spring-orm</artifactId>
  		<version>4.3.12.RELEASE</version>
  	</dependency>
  	
  	<dependency>
  		<groupId>log4j</groupId>
  		<artifactId>log4j</artifactId>
  		<version>1.2.17</version>
  	</dependency>
  	<dependency>
			<groupId>aspectj</groupId>
			<artifactId>aspectjrt</artifactId>
			<version>1.2</version>
		</dependency>
  </dependencies>
  	
  
</project>
创建连接数据的四要素jdbc.properties文件

url=jdbc:mysql://localhost:3306/news
driverClassName=com.mysql.jdbc.Driver
userName1=root
password=123456

创建spring.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:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="
	http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
	http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context-4.2.xsd
	http://www.springframework.org/schema/tx  http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
	http://www.springframework.org/schema/aop  http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
	
	">
	<!-- 扫描bean -->
   <context:component-scan base-package="less04.testm"></context:component-scan>
   <context:property-placeholder location="classpath:/less04/jdbc.properties"/>
   <bean id="dataSource"  class="org.springframework.jdbc.datasource.DriverManagerDataSource">
     <property name="url" value="${url}" ></property>
     <property name="username" value="${userName1}" ></property>
     <property name="password" value="${password}" ></property>
     <property name="driverClassName" value="${driverClassName}" ></property>
   </bean>
   <!-- 事务管理器  不再使用jdbc的commit和rollback 必须由事务管理器提供 -->
   <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
     <property name="dataSource" ref="dataSource"></property> 
   </bean>
   <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
   	   <property name="dataSource" ref="dataSource"></property> 
   </bean>
   <!-- 定义通知  通知的代码 spring已经实现  -->
   <tx:advice id="myAdvise"  transaction-manager="transactionManager">
	   	<tx:attributes>
	   	    <!-- 
	   	       propagation="REQUIRED" 方法和方法之间父子关系
	   	         REQUIRED 没有事务创建一个事务 有事务使用当前事务
	   	         REQUIRED_NEW 不管父方法是否存在事务 都会新建事务
	   	         SUPPORTS 父方法存在事务 使用当前事务  没有事务 使用jdbc的事务(自动提交)
	   	         NOT_SUPPORTED 不管父方法是否存在事务 都不会使用事务(挂起事务)
	   	         MANDATORY 必须在事务环境下运行 父方法没有事务 抛出异常
	   	           No existing transaction found for transaction marked with propagation 'mandatory'
	   	         NEVER 父方法不能存在 事务 有事务抛出异常   
	   	           Existing transaction found for transaction marked with propagation 'never'
	   	           
	   	           isolation="DEFAULT"隔离级别
	   	           	DEFAULT使用数据库本身的隔离级别ORACLE(读已提交)MYSQL(可重复读)
	   	           	READ_UNCOMMITTED spring实现读未提交(脏读)
	   	           	REA_COMMITTED spring实现读已提交(不重复读+幻读)
	   	           	REPEATABLE_READ spring实现可重复读(幻读)
	   	           	SERIALIZABLE spring实现串行化(已解决)
	   	           	
	   	           	spring事务运行过程中碰到运行时异常自动回滚 非运行时异常不会回滚
	   	           	rollback-for=""指定会自动回滚的非运行时异常
	   	           	no-rollback-for=""指定某些运行时异常抛出时不回滚
	   	           	
	   	           	只读事务(除特定的方法以外其他的业务逻辑方法都不应该操作事务)
	   	           	read-only="true"设置只读事务
	   	           	timeout=""设置超时时间
	   	     -->
	   		<tx:method name="update*" propagation="REQUIRED"/>
	   		<tx:method name="save*" />
	   		<tx:method name="delete*"/>
	   		<tx:method name="*" read-only="true"/>
	   	</tx:attributes>
   </tx:advice>
    <!-- 定义切点 advice-ref引用通知 -->
   <aop:config>
   	<aop:pointcut expression="execution(* less04.testm.dao.*.*(..))  " id="myPoint"/>
    <aop:advisor advice-ref="myAdvise" pointcut-ref="myPoint"/>
   </aop:config>
   
   
</beans>


持久层

package less04.testm.dao;

import java.sql.SQLException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
@Repository
public class AcDaoImpl {
	@Autowired
	JdbcTemplate jdbc;
	@Autowired
	BcDaoImpl b;
	public  void updateAminus(int money) throws SQLException{
		//扣钱
		String sql="update mymoney set lostedmoney=lostedmoney-"+money+" where usid=1";
		jdbc.execute(sql);
		
		//加钱
		b.saveBadd(money);
		int i=5/0;
	}
}



package less04.testm.dao;

import java.sql.SQLException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
@Repository
public class BcDaoImpl {
	@Autowired
	JdbcTemplate jdbc;
	public  void saveBadd(int money) throws SQLException{
		String sql="update mymoney set lostedmoney=lostedmoney+"+money+" where usid=2";
		jdbc.execute(sql);
	}
}

测试main方法
import java.sql.SQLException;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;
import less04.testm.dao.AcDaoImpl;

/**
 * 编程式事务 
 * 声明式事务
 *    xml声明(全局)
 *    注解声明
 */

public class TestTa {
	static AcDaoImpl myMoneyDao;
	static{
		ApplicationContext context = new GenericXmlApplicationContext("classpath:less04/testm/spring.xml");
		myMoneyDao=(AcDaoImpl)context.getBean("acDaoImpl");
	}

	public static void main(String[] args) throws SQLException {
		myMoneyDao.updateAminus(10);
	}
	
}

三.事务的隔离级别

1.什么是事务的隔离级别

事务隔离级别指的是一个事务对数据的修改与另一个并行的事务的隔离程度,当多个事务同时访问相同数据时,如果没有采取必要的隔离机制,就可能发生以下问题:

 脏读:一个事务读到另一个事务未提交的更新数据。

    幻读:例如第一个事务对一个表中的数据进行了修改,比如这种修改涉及到表中的“全部数据行”。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入“一行新数据”。那么,以后就会发生操作第一个事务的用户发现表中还存在没有修改的数据行,就好象发生了幻觉一样。

    不可重复读:比方说在同一个事务中先后执行两条一模一样的select语句,期间在此次事务中没有执行过任何DDL语句,但先后得到的结果不一致,这就是不可重复读。

2.Spring支持的隔离级别

1.DEFAULT 使用数据库本身的隔离级别ORACLE(读已提交)MYSQL(可重复读)
2. READ_UNCOMMITTED 读未提交(脏读)最低的隔离级别,一切皆有可能。 spring实现读未提交(脏读)
3.REA_COMMITTED 读已提交,ORACLE默认隔离级别,有幻读以及不可重复读风险 .spring 实现读已提交(不重复读+幻读)
4.REPEATABLE_READ 可重复读,解决不可重复读的隔离级别,但还是有幻读风险.spring实现可重复读(幻读)
5.SERIALIZABLE 串行化,最高隔离级别,杜绝一切隐患,缺点是效率低.spring实现串行化(已解决)

3.事务的回滚

spring事务运行过程中碰到运行时异常自动回滚 非运行时异常不会回滚

rollback-for=""指定会自动回滚的非运行时异常

no-rollback-for=""指定某些运行时异常抛出时不回滚


  timeout=""设置超时时间 超时时间一般在5到20之间

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring是一个开源的Java开发框架,它提供了许多功能和工具,可以帮助开发者更加方便和快速地构建应用程序。 要想从入门到精通Spring,首先需要了解和掌握Spring的核心概念和基本原理。了解Spring MVC等Spring框架的基本工作原理,熟悉Spring的注入(DI)和切面编程(AOP)等重要特性,这是Spring的基石。 其次,学习和掌握Spring框架的各个模块和组件。Spring框架提供了众多的模块,如Spring Boot、Spring Data、Spring Security等,这些模块都有自己的特点和应用场景。了解每个模块的作用和使用方法,能够根据具体需求灵活应用。 进一步,给自己找一个实际的项目来练手。通过实际项目的开发,可以更好地理解Spring的各项功能和特性。在实际项目中,可以使用Spring的依赖注入、AOP、事务管理等特性,提高代码的可维护性和灵活性,加深对Spring框架的理解和掌握。 同时,了解Spring的最新动态和更新。Spring框架在不断的发展和更新,新的版本可能会有一些新的功能和改进,了解并使用新的功能可以提高开发效率和代码质量。 最后,参加相关培训或考取相关认证。Spring的知识非常广泛和庞大,通过参加培训或考取相关认证可以系统地学习和掌握Spring框架的各个方面,提升自己的技术能力和职业竞争力。 总之,要想从入门到精通Spring,需要不断地学习和实践。通过理论和实践相结合,不断提升自己的能力和对Spring的理解,最终可以成为Spring的专家。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值