java-在新的事务范围内更新对象

我有一个与事务性边界有关的问题,我无法弄清楚出了什么问题.

@Transactional( propagation = Propagation.REQUIRED )
Class A {
void methodA() {
     try {
     new B().callMethodB(obj)
     } catch(Exception e) {
           updateSomeProperty(obj1)
     }
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
void updateSomeProperty(Object obj1) {
     obj1.setProperty(1);
     obj1.save();       
}
        }

 Class B {

   public void callMethodB(Object obj) throws Exception {
    throws new Exception();  
 }

 }

问题是抛出错误时我的对象没有更新.我也尝试从updateSomeProperty方法中触发SQL代码,但这也没有用.

基本上,无论是否引发异常,我都想更新对象的属性.
有任何想法吗 ??

最佳答案
而且它不起作用.因为您从类的另一种方法调用updateSomeProperty(obj1)并尝试更改默认的事务行为(从REQUIRED到REQUIRED_NEW).但这是行不通的.这就是为什么发生异常时所有更改都会回滚的原因.

默认情况下,Spring为接口创建代理,并且@Transactional注解仅应用于公共方法.并且应该从“外部”调用此方法.如果要从类中的另一个方法调用它们,则@Transactional注释将不起作用.

您还可以更改xml中事务的默认设置(查看属性proxy-target-class和mode).但是我从未改变过它,也不记得它应该如何工作.

<tx:annotation-driven transaction-manager="txManager" mode="..." proxy-target-class="..."/>

编辑:

顺便说说.这是一个非常好的article about transaction pitfalls.它对我很有帮助.关于事务的其他非常有趣的文章也很少.

编辑2:

再次问好.我认为我找到了解决您问题的方法.至少我对此进行了测试,并且对我来说效果很好.
我建议您将事务模式更改为“ AspectJ”,并为项目使用AspectJ编译时调用.这将使您有可能从一个类中的另一个方法调用具有变化的事务行为的私有事务方法(对于已启动的嵌套事务).在这种情况下,您可以在嵌套事务中进行一些更改,而外部事务将被回滚.为此,您需要执行以下步骤:

1)在交易定义中更改交易模式:
-如果您使用xml配置,则:

<tx:annotation-driven transaction-manager="txManager" mode="aspectj"/>

>如果您使用Java配置,则:

@EnableTransactionManagement(mode = AdviceMode.ASPECTJ,proxyTargetClass = false)

2)将Aspectj依赖项添加到pom:

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>${aspectj.version}</version>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>${aspectj.version}</version>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjtools</artifactId>
    <version>${aspectj.version}</version>
</dependency>

3)向pom添加spring-aspects依赖项:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>3.1.2.RELEASE</version>
    <scope>compile</scope>
</dependency>

4)添加maven插件以启用编译时间筛选:

        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>aspectj-maven-plugin</artifactId>
            <version>1.4</version>
            <configuration>
                <showWeaveInfo>true</showWeaveInfo>
                <source>${compiler.version}</source>
                <target>${compiler.version}</target>
                <Xlint>ignore</Xlint>
                <complianceLevel>${compiler.version}</complianceLevel>
                <encoding>UTF-8</encoding>
                <verbose>false</verbose>
                <aspectLibraries>
                    <aspectLibrary>
                        <groupId>org.springframework</groupId>
                        <artifactId>spring-aspects</artifactId>
                    </aspectLibrary>
                </aspectLibraries>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>compile</goal>
                        <!-- <goal>test-compile</goal> -->
                    </goals>
                </execution>
            </executions>
            <dependencies>
                <dependency>
                    <groupId>org.aspectj</groupId>
                    <artifactId>aspectjrt</artifactId>
                    <version>${aspectj.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.aspectj</groupId>
                    <artifactId>aspectjtools</artifactId>
                    <version>${aspectj.version}</version>
                </dependency>
            </dependencies>
        </plugin>

5)我的pom中也有maven编译器插件,这就是为什么我认为也可以添加它的原因:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
        <compilerVersion>${compiler.version}</compilerVersion>
        <fork>true</fork>
        <source>1.7</source>
        <target>1.7</target>
    </configuration>
</plugin>

*注意:我使用jdk 1.7版.我的编译器和aspectj版本很烂:

<compiler.version>1.7</compiler.version>
<aspectj.version>1.6.12</aspectj.version>

我也有其他库的此类版本(但我认为这不是必需的):

<org.springframework.version>3.1.0.RELEASE</org.springframework.version>
<org.hibernate.version>4.1.0.Final</org.hibernate.version>
<org.springdata.version>1.0.2.RELEASE</org.springdata.version>

您还可以尝试在春季使用加载时间筛选功能,但这是
更加难以配置(这是我的看法),不建议在生产环境中使用它(如我在几篇文章中所读).但是,如果您决定使用它,则可以在Web和Spring参考手册中找到很多信息.

如果您想在不使用maven的情况下使用编译时耗损,那么我不知道如何配置它. (我只用Maven测试过).您可以尝试在Web上找到此类信息,但我不建议这样做,因为使用Maven可以更轻松地处理依赖项(在本示例中,添加必要的插件).

这是我用于测试的示例:

>一些界面:

公共接口TestClassInterface {

void testMethod();

}
>一些实现此接口的测试类:

@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
@零件
公共类TestClass实现TestClassInterface {

@Autowired
private SpringDataFooDAO fooDao;

public void testMethod() {
    try {
        Foo foo = fooDao.findOne(2L);
        System.out.println(TransactionSynchronizationManager.getCurrentTransactionName());
        System.out.println(TransactionSynchronizationManager.isActualTransactionActive());
        foo.setName("should be rolled back");
        new ExceptionThrower().doSomething("default string");
    } catch(Exception e) {
        updateSomeProperty(1L,"Changed name");
        throw new RuntimeException(e);
    }
}

@Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor=Exception.class)
private void updateSomeProperty(long id,String newFooName) {

    System.out.println("   ---   ");
    System.out.println(TransactionSynchronizationManager.getCurrentTransactionName());
    System.out.println(TransactionSynchronizationManager.isActualTransactionActive());

     // Update property of test object.
     Foo foo = fooDao.findOne(id);
     foo.setName(newFooName);    
}

}
>另一个带有引发异常的方法的类:

公共类ExceptionThrower {

public void doSomething(Object obj) throws Exception {
    throw new Exception();  
 }

}

请注意,我从catch块中抛出了异常(我将其作为运行时异常来执行,因为我不需要在上层类中处理它).这对于正确的外部事务回滚是必需的.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


这篇文章主要介绍了spring的事务传播属性REQUIRED_NESTED的原理介绍,具有一定借鉴价值,需要的朋友可以参考下。下面就和我一起来看看吧。传统事务中回滚点的使...
今天小编给大家分享的是一文解析spring中事务的传播机制,相信很多人都不太了解,为了让大家更加了解,所以给大家总结了以下内容,一起往下看吧。一定会有所收获...
这篇文章主要介绍了SpringCloudAlibaba和SpringCloud有什么区别,具有一定借鉴价值,需要的朋友可以参考下。下面就和我一起来看看吧。Spring Cloud Netfli...
本篇文章和大家了解一下SpringCloud整合XXL-Job的几个步骤。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。第一步:整合pom文件,在S...
本篇文章和大家了解一下Spring延迟初始化会遇到什么问题。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。List 坑列表 = new ArrayList(2);...
这篇文章主要介绍了怎么使用Spring提供的不同缓存注解实现缓存的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇...
本篇内容主要讲解“Spring中的@Autowired和@Resource注解怎么使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学...
今天小编给大家分享一下SpringSecurity怎么定义多个过滤器链的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家
这篇文章主要介绍“Spring的@Conditional注解怎么使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Spring的@Con...
这篇文章主要介绍了SpringCloudGateway的熔断限流怎么配置的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇SpringCloud&nb...
今天小编给大家分享一下怎么使用Spring解决循环依赖问题的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考
这篇文章主要介绍“Spring事务及传播机制的原理及应用方法是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Sp...
这篇“SpringCloudAlibaba框架实例应用分析”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价
本篇内容主要讲解“SpringBoot中怎么使用SpringMVC”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习...
这篇文章主要介绍“SpringMVC适配器模式作用范围是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“SpringMVC
这篇“导入SpringCloud依赖失败如何解决”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家...
这篇文章主要讲解了“SpringMVC核心DispatcherServlet处理流程是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来
今天小编给大家分享一下SpringMVCHttpMessageConverter消息转换器怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以...
这篇文章主要介绍“Spring框架实现依赖注入的原理是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Spring框架...
本篇内容介绍了“Spring单元测试控制Bean注入的方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下