学习《spring 3.x企业应用开发实战》之Spring的事务管理

1、数据库事务基础知识
1.1、数据库事务的概念
(1)数据库事物的4个特性(ACID):
  • 原子性(Atomic):表示组成一个事务的多个数据库操作是一个不可分割的原子单元,所有的操作要么全部成功,要么全部失败。
  • 一致性(Consistency):事务操作成功之后,数据库所处的状态和它的业务规则是一致的,即数据不会被破坏。
  • 隔离性(Isolation):在并发数据操作时,不同的事务拥有各自的数据空间,它们的操作不会对对方产生干扰。准确地说,并非要求做到完全无干扰,数据库规定了多种事务隔离级别,不同的隔离级别对应不同的干扰程度,隔离级别越高,数据一致性越好,但并发性越弱。
  • 持久性(Durablity):一旦事务提交成功,事务中所有的数据操作都必须被持久化到数据库中。
在这些特性中,数据“一致性”是最终目标,其他属性都是为达到这一目标的方式手段。

(2) 重执行日志
  • 数据库管理系统一般采用重执行日志保证原子性、一致性和持久性,重执行日志记录了数据库变化的每一个动作。
  • 在一个事务中执行一部分操作发生错误退出,数据库可以根据重执行日志撤销已经执行的操作。
  • 对于已经提交的事务,即使数据库崩溃,在重启数据库时也能够根据日志对尚未持久化的数据进行相应的重执行操作。

(3) 隔离性
和Java程序采用对象锁机制进行线程同步类似,数据库管理系统采用数据库锁机制保证事务的隔离性。Oracle数据库还采用了数据版本的机制,在回滚段为数据的每个变化都保存一个版本,使数据的更改不影响数据的读取。

1.2、数据并发的问题
不可重复读和幻读可理解为多次访问的不幂等
  • 脏读(dirty read):A事务读取B事务尚未提交的更改数据。
  • 不可重复读(unrepeatable read):A事务读取了B事务已经提交的更改数据,即A事务在2次读取的数据不一致。
  • 幻读(plantom read):A事务读取B事务提交的新增数据,幻读一般发生在计算统计数据的事务中。
  • 第一类丢失更新:A事务撤销时,把已经提交的B事务的更新数据覆盖了。
  • 第二类丢失更新:A事务覆盖B事务已经提交的数据,造成B事务所做的操作丢失。

1.3、数据库锁机制
(1)按 锁定的对象不同,分为 表锁定行锁定
(2)从 并发事务锁定的关系上看,可以分为 共享锁定独占锁定
  • 共享锁定会防止独占锁定,但允许其他的共享锁定;
  • 独占锁定既防止其他的独占锁定,也防止其他的共享锁定。
为了更改数据,数据库必须在进行更改的行上施加行独占锁定,insert、update、delete和select for update语句都会隐式采用必要的行锁定。
(3)下面介绍一下Oracle数据库常用的5种锁定:




1.4、事务隔离级别
尽管数据库为用户提供了锁的DML操作方式,但直接使用锁管理是非常麻烦的,因此数据库为用户提供了自动锁机制。
只要用户指定会话的事务隔离级别,数据库就会分析事务中的SQL语句,然后自动为事务操作的数据资源加上合适的锁。此外数据库还会维护这些锁,当一个资源上锁数目太多时,自动进行锁升级以提高系统的运行性能。
(1)ANSI/ISO SQL 92标准定义了4个等级的事务隔离级别:
隔离级别
脏读
不可重复读
幻读
第一类更新丢失
第二类更新丢失
读未提交


×

读提交
×


×

可重复读
×
×

×
×
序列化
×
×
×
×
×
(2)我们一般采用读提交的方式

1.5、JDBC对事务支持
(1)不是所有的数据库都支持事务,也不是所有支持事务的数据库都支持所有的事务隔离级别。用户可以通过 ConnectiongetMetaData()方法获取 DatabaseMetaData对象,并通过该对象的 supportsTransactions()方法和 supportsTransactionIsolationLevel(int level)方法查看底层数据库的事务支持情况。
(2)Connection默认情况是自动提交事务的,即每条sql都对应一个事务,为了将多条sql当成一个事务执行,必须通过 Connection#setAutoCommit(false)阻止Connection自动提交,并通过 Connection#setTransactionIsolation()设置事务的隔离级别,下面是典型的JDBC事务数据操作代码:


(3)在JDBC2.0中,事务只有2个操作:提交和回滚。JDBC3.0以后,引入了保存点的特性,Savepoint接口允许用户将事务分割为多个阶段,用户可以指定回滚到事务的特定保存点。一个使用的例子如下:


并非所有的数据库都支持保存点功能,用户可以通过 DatabaseMetaData#savePoints()方法方法查看是否支持。


2、ThreadLocal基础知识
前面我们知道,Spring通过各种模板类降低了开发者使用各种数据持久化技术的难度。这些模板类都是线程安全的,也就是说多个DAO可以复用同一个模板实例而不会发生冲突,Spring通过ThreadLocal解决了模板类绑定数据连接和会话资源时的并发问题。

2.1、ThreadLocal是什么
(1)ThreadLocal的接口方法
  • void  set(Object  value):设置当前线程的线程局部变量。
  • public  Object  get():返回当前线程的线程局部变量。
  • public  void  remove():删除当前线程的线程局部变量,目的是为了减少内存占用。需要注意的是,当线程结束后,对应该线程的局部变量将自动被垃圾回收,所以显式地调用次方法不是必须的,但是可以加快内存回收的速度。
  • protected  Object  initialValue():返回当前线程的线程局部变量的初始值,
jdk5.0以后,ThreadLocal已经支持泛型了,变为ThreadLocal<T>。

(2)ThreadLocal是如何做到为每一个线程维护一份独立的变量副本呢?
其实实现思路很简单:在ThreadLocal中有一个Map,用于存储每一个线程的变量副本,Map中元素的key为线程对象,而value就是对应线程的变量副本。

2.2、与Thread同步机制的比较
ThreadLocal采用“以空间换时间”的方式:访问并行化,对象独享化。

2.3、Spring使用ThreadLocal解决线程安全问题
在Spring中,绝大部分Bean都可以声明为singleton,就是因为Spring对一些Bean采用了ThreadLocal进行封装。一般情况下从接收请求到返回响应所经过的所有程序调用都同属于一个线程。

3、Spring对事务管理的支持
Spring为事务管理提供了一致的编程模板,在高层次建立了统一的事务抽象。像Spring DAO为不同的持久化技术实现提供模板类一样,Spring事务管理继承了这一风格,也提供了事务模板类 TransactionTemplate。通过TransactionTemplate并配合使用事务回调TransactionCallback指定具体的持久化操作就可以通过编程方式实现事务管理,而无须关注资源获取、复用、释放、事务同步和异常处理的操作。

3.1、事务管理关键抽象
(1)在Spring事务管理SPI的抽象层主要包括3个接口,分别是 PlatformTransactionManagerTransactionDefinitionTransactionStatus,它们位于org.springframework.transaction包中。3者关系如图:


其中,TransactionDefinition用于描述事务的隔离级别,超时时间、是否为只读事务和事务传播规则等控制事务具体行为的事务属性。这些事务属性可以通过XML配置、注解描述或手工编程的方式设置。PlatformTransactionManager根据TransactionDefinition提供的事务属性配置信息创建事务,并用TransactionStatus描述这个激活事务的状态。

(2) TransactionDefinition
  • 事务隔离:TransactionDefinition使用了java.sql.Connection接口中同名的4个隔离级别,此外,TransactionDefinition还定义了一个默认的隔离级别,它表示使用底层数据库的默认隔离级别。
  • 事务传播:通常在一个事务中执行的所有代码都会同一事务的上下文中。但是Spring也提供了几个可选的事务传播类型,例如简单地参与到现有的事务中,或者挂起当前的事务,创建一个新事务。
  • 事务超时:超过时间后,事务被回滚。有些事务管理器不支持事务过期的功能,这时如果设置TIMEOUT_DEFAULT等值时将抛出异常。
  • 只读状态:只读事务不修改任何数据,主要用于优化,如果更改数据就会抛出异常。

(3) TransactionStatus
①TransactionStatus代表一个事务的具体运行状态,事务管理器通过该接口获 取事务的运行期状态信息,也可以通过该接口 间接地回滚事务,它相比于在抛出异常时回滚事务的方式更具有可控性。该接口继承于 SavepointManager接口,SavepointManager接口基于JDBC3.0保存点的分段事务控制能力提供了嵌套事务的机制。
其中,SavepointManager接口拥有以下的方法:
  • Object  createSavepoint():创建一个保存点对象,以便在后面可以利用rollbackToSavepoint(Object  savepoint)方法使事务回滚到特定的保存点上,也可以通过releaseSavepoint()释放一个已经不用的保存点。
  • void  rollbackToSavepoint(Object  savepoint):将事务回滚到特定保存点上,被回滚的保存点将自动释放。
  • void  releaseSavepoint(Object  savepoint):释放一个保存点,如果事务提交,所有保存点会被自动释放,无须手工清除。
这3个方法在底层资源不支持保存点时,都将抛出NestedTransactionNotSupportedException异常。
②TransactionStatus扩展了SavepointManager并提供了以下方法:
  • boolean  hasSavepoint():判断当前的事务是否在内部创建了一个保存点,保存点是为了支持Spring的嵌套事务而创建的。
  • boolean  isNewTransaction():判断当前事务是否是一个新的事务,如果返回false,表示当前事务是一个已经存在的事务,或者当前操作未运行在事务环境中。
  • boolean  isCompleted():判断当前事务是否已经结束(已经提交或回滚)。
  • boolean  isRollbackOnly():判断当前事务是否已经被标识为rollback-only。
  • void  setRollbackOnly():将当前的事务设置为rollback-only,通过该标识通知事务管理器只能将事务回滚,事务管理器将显式调用回滚命令或以抛出异常的方式回滚事务。

(4) PlatformTransactionManager
PlatformTransactionManager是事务的最高层抽象,它提供了3个接口方法:
  • TransactionStatus  getTransaction(TransactionDefinition  definition):该方法根据事务定义信息从事务环境中返回一个已存在的事务,或者创建一个新的事务,并用TransactionStatus描述这个事务的状态。
  • commit(TransactionStatus  status):根据事务的状态提交事务,如果事务状态已经被标识为rollback-only,该方法将执行一个回滚事务的操作。
  • rollback(TransactionStatus  status):回滚事务,当提交事务抛出异常时,回滚会被隐式执行。

3.2、Spring的事务管理器实现类
(1)Spring将事务管理委托给底层具体的持久化实现框架完成,因此Spring为不同的持久化框架提供了PlatformTransactionManager接口的实现类,如下图:


这些事务管理器都是对特定事务实现框架的代理,这样我们就可以通过spring的高级抽象,对不同种类的事务实现使用相同的方式进行管理。

(2)Spring JDBC和iBatis
配置如下:
<bean    id=" dataSource"    class="org.apache.commons.dbcp.BasicDataSource"     destory-method="close"
        p:driverClassName="com.mysql.jdbc.Driver"
        p:url="jdbc:mysql://数据库服务器ip:端口/数据库实例名"
        p:username="数据库用户名"
        p:password="密码"/ >
<!--  基于数据源的事务管理器  -->
<bean    id=" transactionManager"            class=" org.springframework.jdbc.datasource.DataSourceTransactionManager"
        p:dataSource-ref=" dataSource"/>
在幕后,DataSourceTransactionManager使用DataSource的Connection的commit()、rollback()等方法管理事务。

(3)JPA
    JPA通过javax.persistence.EntityTransaction管理JPA的事务,EntityTransaction对象可以通过javax.persistence.EntityManager#getTransaction()获得,而EntityManager又通过一个工厂类方法获取javax.persistence.EntityManagerFactory#createEntityManager()。
    在底层,JPA依然通过JDBC的Connection的事务方法完成最终的控制,因此要配置一个JPA事务管理器,还要先提供一个DataSource,然后配置一个EntityManagerFactory,最后才配置JpaTransactionManager。
配置文件如下:
......
<bean    id=" entityManagerFactory"    class=" org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
        p:dataSource-ref=" dataSource"/>
<bean    id=" transactionManager"    class=" org.springframework.orm.jpa.JpaTransactionManager"
        p:entityManagerFactory-ref=" entityManagerFactory"/>

(4)Hibernate
Spring3.x取消了对Hibernate 2.x的支持,只支持Hibernate 3.x。
配置如下:

(5)JTA
如果希望在Java EE容器里使用JTA,我们将通过JNDI和Spring的JtaTransactionManager获取一个容器管理的DataSource。JtaTransactionManager不需要知道DataSource和其他特定的资源,因为它引用容器提供的全局事务管理。
配置如下:



3.3、事务同步管理器
    Spring将JDBC的Connection、Hibernate的Session等访问数据库的连接或会话对象统称为资源。这些资源在同一时刻是不能多线程共享的,为了让DAO、Service能做到singleton,Spring的事务同步管理器类org.springframework.transaction.support.TransactionSynchronizationManager使用ThreadLocal为不同事务线程提供了独立的资源副本,同时维护事务配置的属性和运行状态信息。
    Spring框架为不同的持久化技术提供了一套从TransactionSynchronizationManager中获取对应线程绑定资源的工具类,如图所示:


  • 当需要脱离模板类,手工操作底层持久化技术的原生API时,就需要通过这些工具类获取线程绑定的资源,而不应该直接从DataSource或SessionFactory中获取。因为后者不能获得和本线程相关的资源。
  • 这些工具类还有另外一个重要的用途:将特定异常转换为Spring的DAO异常。

3.4、事务传播行为
(1)在一个service接口中可能会调用另一个service接口的方法,以共同完成一个完整的业务操作,Spring通过事务传播行为控制当前的事务如何传播到被嵌套调用的目标服务接口方法中。Spring在TransactionDefinition接口中规定了7种类型的事务传播行为,如下图:

当使用PROPAGATION_NESTED时,底层的数据源必须基于JDBC3.0,并且实现者需要支持保存点事务机制。


4、编程式的事务管理
Spring为编程式事务管理提供了模板类org.springframework.transaction.support.TransactionTemplate,和那些持久化模板类一样,TransactionTemplate也是线程安全的。TransactionTemplate有2个重要的方法:
  • void  setTransactionManager(PlatformTransactionManager  transactionManager):设置事务管理器。
  • Object  execute(TransactionCallback  action):在TransactionCallback回调接口中定义需要以事务的方式组织的数据访问逻辑。
TransactionCallback接口只有一个方法:Object  doInTransaction(TransactionStatus  status)。如果操作不会返回结果,可以使用TransactionCallback的子接口TransactionCallbackWithoutResult。

5、使用XML配置声明式事务

5.1、使用原始的TransactionProxyFactoryBean
在早期的版本中,spring要求用户通过TransactionProxyFactoryBean对需要事务管理的业务类进行代理。现在已经不推荐使用,但是仍然可用。
(1) 声明式事务配置
使用TransactionProxyFactoryBean配置事务如下:


(2) 异常回滚/提交规则
上图<prop/>内的值为事务属性信息,其配置格式如下:


用户可以通过显式指定回滚规则:通过指定带正号(+)或负号(-)的异常类名(或异常名匹配片段),并且Exception可以配置多个。

5.2、基于tx/aop命名空间的配置
下面是通过tx/aop配置事务的示例:



如果事务管理器命名为transactionManager,则<tx:advice/>可以不指定transaction-manager属性。

<tx:method/>替代了之前TransactionProxyFactoryBean使用逗号分隔的方式配置事务属性,如果需要为不同的业务Bean采取不同的事务属性配置,则可以在<aop:config/>中定义多个切面。<tx:method/>属性表如下:


使用aop/tx配置的声明式事务管理是使用最广泛的,因为它的表达能力最强,且使用灵活。


6、使用注解配置声明式事务
6.1、使用@Transactional注解
(1)@Transactional可以用于标注类和类的 public方法,当然,注解只是元数据,它本身并不能完成事务切面织入的功能,因此我们还要在Spring配置文件中,通过一行配置“通知”Spring对标注@Transactional的Bean进行加工处理。如下:
。。。
<!-- 对标注@Transactional的Bean进行加工处理,以织入事务管理切面 -->
<tx:annotation-driven    transaction-manager="txManager"/>
(2)<tx:annotation-driven/>会 自动使用名为 transactionManager的事务管理器,所以如果用户的事务管理器id为transactionManager,可以进一步将上面的配置 简化为<tx:annotation-driven/>
(3)<tx:annotation-driven/>还要另外2个属性:
  • proxy-target-class:true表示使用cglib创建代理类,false表示使用jdk创建代理类。
  • order:如果业务类除事务切面外,还需要织入其他的切面,通过该属性可以控制事务切面在目标连接点的织入顺序。
(4)@Transactional属性说明如图:

@Transactional有一组普适性的默认事务属性:
  • 事务传播行为:PROPAGATION_REQUIRED;
  • 事务隔离级别:ISOLATION_DEFAULT;
  • 读写事务属性:读/写事务;
  • 超时时间:依赖于底层的事务系统的默认值;
  • 回滚设置:任何运行期异常引发回滚,任何检查型异常不会引发回滚。
有2点需要注意:
  • 如果不设置rollbackFor,那么只有运行期异常会被回滚,检查型异常不会回滚;
  • rollbackForClassName是通配符匹配,即只要有几个字符匹配就行;
  • 就算指定了rollbackForClassName的检查型异常,程序遇到运行期异常,依然会引发回滚。

(5)在何处标注@Transactional注解
@Transactional注解可以被应用于接口和接口方法,类和类的 public方法上( 类级的注解适用于类中的所有public方法,方法处的注解会覆盖类定义处的注解)。但Spring建议在业务实现类上使用@Transactional注解,因为注解不能被继承,所以用在接口上会有隐患。即使<tx:annotation-driven/>的proxy-target-class属性设置为true,业务类照样工作在非事务的环境下。

(6)使用不同的事务管理器



6.2、通过引入AspectJ LTW在类加载期引入事务切面

7、集成特定的应用服务器
一般来说Spring事务抽象与应用服务器是无关的,如果用户希望事务管理器使用特定的UserTransaction和TransactionManager对象,以获取更多的事务控制功能,这时可以采用Spring为集成这些应用服务器所提供的适配器。


智能网联汽车的安全员高级考试涉及多个方面的专业知识,包括但不限于自动驾驶技术原理、车辆传感器融合、网络安全防护以及法律法规等内容。以下是针对该主题的一些核心知识解析: ### 关于智能网联车安全员高级考试的核心内容 #### 1. 自动驾驶分级标准 国际自动机工程师学会(SAE International)定义了六个级别的自动驾驶等级,从L0到L5[^1]。其中,L3及以上级别需要安全员具备更高的应急处理能力。 #### 2. 车辆感知系统的组成与功能 智能网联车通常配备多种传感器,如激光雷达、毫米波雷达、摄像头和超声波传感器等。这些设备协同工作以实现环境感知、障碍物检测等功能[^2]。 #### 3. 数据通信与网络安全 智能网联车依赖V2X(Vehicle-to-Everything)技术进行数据交换,在此过程中需防范潜在的网络攻击风险,例如中间人攻击或恶意软件入侵[^3]。 #### 4. 法律法规要求 不同国家和地区对于无人驾驶测试及运营有着严格的规定,考生应熟悉当地交通法典中有关自动化驾驶部分的具体条款[^4]。 ```python # 示例代码:模拟简单决策逻辑 def decide_action(sensor_data): if sensor_data['obstacle'] and not sensor_data['emergency']: return 'slow_down' elif sensor_data['pedestrian_crossing']: return 'stop_and_yield' else: return 'continue_driving' example_input = {'obstacle': True, 'emergency': False, 'pedestrian_crossing': False} action = decide_action(example_input) print(f"Action to take: {action}") ``` 需要注意的是,“同学”作为特定平台上的学习资源名称,并不提供官方认证的标准答案集;建议通过正规渠道获取教材并参加培训课程来准备此类资格认证考试
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值