spring通过TransactionInterceptor和AbstractPlatformTransactionManager的实现类控制数据库事务。
创建数据库
Animal表
create table Animal(
name nvarchar(20)
)
Person表
create table Person(
name nvarchar(20)
)
一、配置文件
1.applicationContext.xml
<import resource="applicationContext-common.xml"/>
<import resource="applicationContext-service.xml"/>
2.applicationContext-service.xml
<bean id="baseService" abstract="true">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="animalService" class="service.impl.AnimalServiceImpl" parent="baseService"/>
<bean id="personService" class="service.impl.PersonServiceImpl" parent="baseService"/>
<bean id="allService" class="service.impl.AllServiceImpl" parent="baseService">
<property name="animalService" ref="animalService"/>
<property name="personService" ref="personService"/>
</bean>
3.applicationContext-common.xml
<!-- 配置属性配置文件 -->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:jdbc.properties</value>
</list>
</property>
</bean>
<!-- 配置数据源 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.database.driverClassName}"/>
<property name="url" value="${jdbc.database.url}"/>
<property name="username" value="${jdbc.database.username}"/>
<property name="password" value="${jdbc.database.password}"/>
</bean>
<!-- 配置事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 具体事务配置 -->
<aop:config>
<aop:pointcut expression="execution(* service.*.*(..))"
id="allManagerMethods" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="allManagerMethods" />
</aop:config>
<!-- 事务传播特性的配置 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>
4.jdbc.properties
jdbc.database.driverClassName=oracle.jdbc.driver.OracleDriver
jdbc.database.url=jdbc:oracle:thin:@127.0.0.1:1521:oracle
jdbc.database.username=scott
jdbc.database.password=tiger
二、service类
service.AllService
public interface AllService {
public void addAll(String personName,String animalName) throws Exception;
}
service.impl.AllServiceImpl
public class AllServiceImpl extends JdbcDaoSupport implements AllService {
private PersonService personService;
private AnimalService animalService;
@Override
public void addAll(String personName, String animalName) throws Exception {
try{
personService.addPerson(personName);
}catch (Exception e) {
System.out.println(e.toString());
}
animalService.addAnimal(animalName);
}
public void setPersonService(PersonService personService) {
this.personService = personService;
}
public void setAnimalService(AnimalService animalService) {
this.animalService = animalService;
}
}
service.AnimalService
public interface AnimalService {
public void addAnimal(String animalName) throws Exception;
}
service.impl.AnimalServiceImpl
public class AnimalServiceImpl extends JdbcDaoSupport implements AnimalService{
@Override
public void addAnimal(String animalName) throws Exception {
this.getJdbcTemplate().update("insert into ANIMAL values(?)",new Object[]{animalName});
}
}
service.PersonService
public interface PersonService {
public void addPerson(String personName)throws Exception;
}
service.impl.PersonServiceImpl
public class PersonServiceImpl extends JdbcDaoSupport implements PersonService {
@Override
public void addPerson(String personName) throws Exception {
this.getJdbcTemplate().update("insert into PERSON values(?)",new Object[]{personName});
}
}
三、测试代码
public class SpringTest {
private static ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"applicationContext.xml");
public static void main(String[] args) throws Exception{
AllService allService=(AllService) applicationContext.getBean("allService");
String personName="will";
String animalName="小狗";
allService.addAll(personName,animalName);
}
}
执行以上代码,在数据库中可以成功插入数据。
可是如果把personName赋值为一个很长的字符串(超过20位,超过数据库指定长度),就会抛出如下错误
org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback; uncategorized SQLException for SQL [insert into PERSON values(?)]; SQL state [72000]; error code [12899]; ORA-12899: 列 "SCOTT"."PERSON"."NAME" 的值太大 (实际值: 32, 最大值: 20)
; nested exception is java.sql.SQLException: ORA-12899: 列 "SCOTT"."PERSON"."NAME" 的值太大 (实际值: 32, 最大值: 20)
Exception in thread "main" org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:695)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:321)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:116)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at $Proxy2.addAll(Unknown Source)
at test.SpringTest.main(SpringTest.java:16)
已经在AllServiceImpl中的addAll中捕获了personService.addPerson这个抛出异常的方法调用。从控制台的打印中,可以发现错误的源是插入的Person表中的name字段太长。虽然在AllServiceImpl.addAll中已经捕获了异常,AllServiceImpl.addAll并未抛出异常,可是事务还是没有提交成功。
经过调试,发现spring处理普通的jdbc事物大致如此:每当调用事物管理的方法时(这里就是aop:pointcut expression匹配的方法),首先会调用TransactionInterceptor的invoke方法,在方法中spring会检测是否要开启事物(根据具体的配置文件而定),然后具体在调用具体的那个真正要处理的方法。如果这个真正处理的方法抛出了异常(如果在这个真正执行的方法内部有异常,但是自我捕获了,那么对于spring而言,这个方法并没有抛出异常),spring会根据配置判断这个异常是否要使得事物回滚,如果要回滚,那么就是设置一个标记,标记有关这一个connection的所有事物都要回滚。
所以,虽然AllServiceImpl.addAll中没有抛出异常,但是personService.addPerson这个调用抛出了异常,并且这个方法spring是要做事物处理的,一旦personService.addPerson抛出异常,TransactionInterceptor中invoke方法会捕获这个异常,然后标记有关这个connection的事务做回滚,就算在AllServiceImpl.addAll捕获了这个异常,但是animalService.addAnimal是无法插入数据的
分享到:
相关推荐
在IT领域,SpringBoot、Activiti和Oracle是三个非常重要的技术组件,它们分别代表了现代企业级应用开发的三大支柱:轻量级框架、工作流引擎和关系型数据库。本项目将这三者进行了深度整合,构建了一个高效、便捷的...
org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only at org.springframework.transaction.support....
org.springframework.transaction-3.2.2.RELEASE最新版本
org.springframework.transaction-3.1.0.M2
Spring中的事务管理问题:org.springframework.transaction-3.1.0.M1.jar包。org.springframework.transaction-3.1.0.M1.jar包。
org.springframework.transaction-3.1.0.M1.jar
"spring-transaction.jar"正是提供了Spring事务管理的类库,它包含了一系列用于处理事务的接口、类和配置元素,使得开发者能够方便地实现事务控制。 一、Spring 事务管理概述 Spring事务管理分为编程式事务管理和...
org.springframework.transaction-3.2.4.RELEASE.jar,最新版的org.springframework.transaction,Wed Aug 07 16:44:37 GMT+01:00 2013
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.transaction.interceptor.TransactionInterceptor#0': Error setting property values; nested ...
org.springframework.transaction-3.0.0.M4.jar
org.springframework.transaction-sources-3.0.1.RELEASE-A.jar 免费下载 org.springframework.transaction-sources-3.0.1.RELEASE-A.jar 源码,免费下载 如果不能免费下载,关注我,评论区联系我索要!
例如,当一个方法抛出未检查异常(继承自RuntimeException的异常)时,Spring会自动回滚事务,而检查异常(非RuntimeException)则不会导致回滚,除非明确指定`rollbackFor`属性。 最后,结合`Book1.xlsx`这个...
分布式事务框架LCN支持springcloud 2.0.5 ,transaction-springcloud-4.1.2.jar
《Spring Boot事务管理实战教程——基于spring-transaction-demo项目》 在软件开发中,事务管理是确保数据一致性、完整性和可靠性的关键环节。本教程将以`spring-transaction-demo`项目为示例,深入探讨如何在...
赠送jar包:javax.transaction-api-1.2.jar; 赠送原API文档:javax.transaction-api-1.2-javadoc.jar; 赠送源代码:javax.transaction-api-1.2-sources.jar; 赠送Maven依赖信息文件:javax.transaction-api-1.2....
java运行依赖jar包
### Spring中的Transaction事务传播行为种类详解 #### 一、引言 在开发基于Spring框架的应用程序时,事务管理是确保数据一致性的重要手段之一。Spring框架提供了丰富的事务管理功能,其中包括了事务传播行为...
编程式事务管理需要开发者手动调用 begin/commit/rollback 方法,而声明式事务管理则更简洁,只需在方法上添加 @Transactional 注解,Spring 就会自动处理事务的开始、提交和回滚。 **SSI 集成** 在 "17-Prj-...
在IT行业中,Spring框架是Java开发中的核心工具之一,尤其在企业级应用中,它提供了丰富的功能,包括依赖注入、AOP(面向切面编程)以及我们今天将要讨论的重点——事务管理。这个名为"springTransaction.rar"的...
本文将围绕“asec-w04-derived-unique-token-per-transaction - APT”这一主题,深入探讨工控安全、数据泄露、勒索软件、大数据以及高级持续性威胁(APT)等关键知识点,同时也会提及安全集成、企业安全策略以及零...