我已经配置了带注释驱动的spring jpa。我希望以下代码在方法存在时将更改持久保存到数据库中。
@Transactional
public Foo changeValue(int id){
final Foo foo = fooRepository.findOne(id);
if(foo != null){
foo.setValue("new value");
//fooRepository.save(foo);
}
}
FooRepository
是JPARepository
,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" />
答案 0 :(得分:2)
您的一般方法是正确的。应该在退出方法时保存并提交更改。虽然这种方法在工作时效果很好,但它是一个调试的婊子。
您的配置对我来说没问题,所以我会仔细检查一下,您实际上可以使用Spring Bean而不是通过调用构造函数创建的实例。
要验证这一点,只需在调用带注释方法的代码点放置一个断点即可。带注释方法的bean不应该是你编写的类,而是一些ProxySomething
类。
本文还提供了一些可能与您的设置有关的错误信息。
答案 1 :(得分:1)
如果您同时拥有ContextLoaderListener
和DispatcherServlet
,则它们都会加载配置文件。
根据您的配置判断,DispatcherServlet
加载了服务,<tx:annotation-driven />
加载了您的ContextLoaderListener
。它们都创建了ApplicationContext
,并且AOP仅应用于同一上下文中的bean,您的服务将不是事务性的(事务管理是通过使用AOP完成的)。
根据经验,您的ContextLoaderListener
应包含所有共享或全局资源(如服务,daos,数据源等),而您的DispatcherServlet
应仅包含与控制器,视图解析器等Web相关的bean