事务注释不会在退出时保存

时间:2015-06-02 20:39:34

标签: spring hibernate jpa transactions

我已经配置了带注释驱动的spring jpa。我希望以下代码在方法存在时将更改持久保存到数据库中。

@Transactional
public Foo changeValue(int id){
    final Foo foo = fooRepository.findOne(id);
    if(foo != null){
       foo.setValue("new value");
       //fooRepository.save(foo);
    }
}

FooRepositoryJPARepository,foo对象被获取,因此它被管理。根据我读到的@Transactional 我希望,即使没有fooRepository.save(foo)调用,数据库中foo值列的更改也会在方法存在时保留。但是,只有在我取消对fooRepository.save(foo)

的调用取消注释时才会发生这种情况

不抛出任何异常,jpa数据源的配置如下所示。

  <bean id="entityManagerFactory"  class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
   ...
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
    p:entityManagerFactory-ref="entityManagerFactory" />

<tx:annotation-driven transaction-manager="transactionManager" />

<context:component-scan
    base-package="com.example.package.data" />

<jpa:repositories
    base-package="com.example.package.data.repository"
    entity-manager-factory-ref="entityManagerFactory"
    transaction-manager-ref="transactionManager" />

有什么想法吗?

更新

我有一个ContextLoaderListener和一个DispatcherServlet但我没有组件扫描。

    <servlet>
    <servlet-name>appServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
    </init-param>
    </servlet>
    ....
    <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

更新

    <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring/root-context.xml</param-value>

    </context-param>

我在那里

    <context:component-scan base-package="com.example.package">
 <context:exclude-filter type="regex" 
        expression="com.example.package.data.*" />
 <context:exclude-filter type="regex" 
        expression="com.example.package.web.controller.*" />    
 <context:exclude-filter type="regex" 
        expression="com.example.package.web.service.*" />       
</context:component-scan>

并在servlet-context

<context:component-scan base-package="com.example.package.web" />

2 个答案:

答案 0 :(得分:2)

您的一般方法是正确的。应该在退出方法时保存并提交更改。虽然这种方法在工作时效果很好,但它是一个调试的婊子。

您的配置对我来说没问题,所以我会仔细检查一下,您实际上可以使用Spring Bean而不是通过调用构造函数创建的实例。

要验证这一点,只需在调用带注释方法的代码点放置一个断点即可。带注释方法的bean不应该是你编写的类,而是一些ProxySomething类。

本文还提供了一些可能与您的设置有关的错误信息。

答案 1 :(得分:1)

如果您同时拥有ContextLoaderListenerDispatcherServlet,则它们都会加载配置文件。

根据您的配置判断,DispatcherServlet加载了服务,<tx:annotation-driven />加载了您的ContextLoaderListener。它们都创建了ApplicationContext,并且AOP仅应用于同一上下文中的bean,您的服务将不是事务性的(事务管理是通过使用AOP完成的)。

根据经验,您的ContextLoaderListener应包含所有共享或全局资源(如服务,daos,数据源等),而您的DispatcherServlet应仅包含与控制器,视图解析器等Web相关的bean