我正在尝试使用aspectj和编译时编织来支持Spring的@Transactional和@Configurable等注释。我正在使用org.springframework.orm.jpa.JpaTransactionManager事务管理器,当我尝试在我的GenericDAO中调用entityManager.persist(entity)时,我在日志中看到的是这样的:
insurance-module-0.1-SNAPSHOT 19:57:55.199 [http-bio-8084-exec-49] TRACE org.hibernate.loader.Loader - Bound [6] parameters total
insurance-module-0.1-SNAPSHOT 19:57:55.199 [http-bio-8084-exec-49] TRACE org.hibernate.loader.Loader - processing result set
insurance-module-0.1-SNAPSHOT 19:57:55.199 [http-bio-8084-exec-49] DEBUG org.hibernate.loader.Loader - result set row: 0
insurance-module-0.1-SNAPSHOT 19:57:55.199 [http-bio-8084-exec-49] TRACE o.h.t.descriptor.sql.BasicExtractor - found [1] as column [id3_]
insurance-module-0.1-SNAPSHOT 19:57:55.199 [http-bio-8084-exec-49] DEBUG org.hibernate.loader.Loader - result row: EntityKey[com.vendio.insurance.domain.db.InsuranceRate#1]
insurance-module-0.1-SNAPSHOT 19:57:55.199 [http-bio-8084-exec-49] TRACE org.hibernate.loader.Loader - done processing result set (1 rows)
insurance-module-0.1-SNAPSHOT 19:57:55.200 [http-bio-8084-exec-49] TRACE org.hibernate.loader.Loader - total objects hydrated: 0
insurance-module-0.1-SNAPSHOT 19:57:55.200 [http-bio-8084-exec-49] DEBUG o.h.e.StatefulPersistenceContext - initializing non-lazy collections
insurance-module-0.1-SNAPSHOT 19:57:55.200 [http-bio-8084-exec-49] TRACE org.hibernate.impl.SessionImpl - after transaction completion
insurance-module-0.1-SNAPSHOT 19:57:55.201 [http-bio-8084-exec-49] TRACE o.s.t.s.TransactionSynchronizationManager - Retrieved value [org.springframework.orm.jpa.EntityManagerHolder@5ec859c1] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@337cbe84] bound to thread [http-bio-8084-exec-49]
insurance-module-0.1-SNAPSHOT 19:57:55.209 [http-bio-8084-exec-49] DEBUG org.hibernate.SQL - select sequence_next_hi_value from hibernate_sequences where sequence_name = 'registered_policy' for update
insurance-module-0.1-SNAPSHOT 19:57:55.210 [http-bio-8084-exec-49] DEBUG org.hibernate.SQL - update hibernate_sequences set sequence_next_hi_value = ? where sequence_next_hi_value = ? and sequence_name = 'registered_policy'
insurance-module-0.1-SNAPSHOT 19:57:55.218 [http-bio-8084-exec-49] TRACE o.s.t.s.TransactionSynchronizationManager - Retrieved value [org.springframework.orm.jpa.EntityManagerHolder@5ec859c1] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@337cbe84] bound to thread [http-bio-8084-exec-49]
所以每个表的hibernate序列都会更新,但我的实体没有插入到数据库中。
如果我添加了entityManager.flush(),则会出现一个异常,说明“没有正在进行的事务”。
这里发生了什么?!
我的GenericDAO类看起来像这样:
public class GenericDAO<T extends Persistable> {
@PersistenceContext
protected EntityManager entityManager;
@PersistenceUnit
protected EntityManagerFactory entityManagerFactory;
@Transactional
public void saveOrUpdate(T entity) {
entityManager.persist(entity);
}
}
我从使用WSSpringServlet导出的网络服务中调用saveOrUpdate方法。
P.S。:我的Maven配置看起来像这样:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.4</version>
<configuration>
<complianceLevel>1.6</complianceLevel>
<showWeaveInfo>true</showWeaveInfo>
<aspectLibraries>
<aspectLibrary>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</aspectLibrary>
</aspectLibraries>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
编译时,我得到一些看起来不错的东西(我的方面得到应用):
Join point 'method-call(void javax.persistence.EntityManager.persist(java.lang.Object))'
in Type 'com.vendio.insurance.dao.GenericDAO' (GenericDAO.java:28)
advised by afterThrowing advice from 'org.springframework.orm.jpa.aspectj.JpaExceptionTranslatorAspect'
(spring-aspects-3.1.0.RELEASE.jar!JpaExceptionTranslatorAspect.class:14(from JpaExceptionTranslatorAspect.aj))
我的相关Spring配置是:
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<context:component-scan base-package="com.vendio.insurance" />
<context:spring-configured/>
<!-- <bean class="org.springframework.transaction.aspectj.AnnotationTransactionAspect" factory-method="aspectOf">
<property name="transactionManager" ref="transactionManager"/>
</bean>-->
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager" />
所以一切看起来都不错,但我找不到为什么这不起作用的答案......
答案 0 :(得分:3)
我在此链接后找到了答案:http://forum.springsource.org/showthread.php?18953-DispatcherServlet-and-ContextLoaderListener。
这个问题是由于我还在使用Spring MVC并且我在不知道两个几乎相同的Spring上下文的情况下创建的。因此,事务管理器在第一个上下文(接收JAX-WS调用的那个)中管理事务,但我调用的实体管理器由第二个上下文管理(使用不同的事务管理器)。
解决方案是隔离DispatcherServlet的小的简化上下文定义,并让其余的bean由ContextLoaderListener管理:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/application-context.xml</param-value>
</context-param>
<servlet>
<servlet-name>spring-mvc-dispatcher-servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>2</load-on-startup>
<init-param>
<param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring/servlet-context.xml</param-value>
</init-param>
</servlet>
由于我使用了基于注释的MVC(使用@Controller注释),我还必须减少上下文的范围:“servlet”上下文中的component-scan的base-package。
以下是保存我一天的链接的引用:
DispatcherServlet将始终使用-servlet.xml加载自己的配置文件。此文件旨在包含Web组件,如Controllers,ViewResolvers和LocaleResolvers - 但不包含中间层组件。
然后使用ContextLoaderListener加载包含中间层和数据层组件的文件。 Spring会将所有这些组件合并到一个ApplicationContext中,使您的中间层组件可以从Web层组件中访问。 &gt; Rob Harrop首席工程师,dm服务器
答案 1 :(得分:0)
如果您使用EntityManager,则不必处理代码中的任何休眠问题。 这正是jpa的用途。
前段时间我遇到了同样的问题。
您的EntityManager必须注入@PersistenceContext。 getEntityManager()不会这样做。
您的注释功能必须公开。
答案 2 :(得分:0)
所以每个表的hibernate序列都会更新,但我的实体没有插入到数据库中。
即使没有两个相同的Spring上下文的问题,我也遇到了相同的症状。 forceAjcCompile选项解决了问题:
...
<java.version>1.6</java.version>
<aspectj.version>1.7.0</aspectj.version>
...
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.6</version>
<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>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
<configuration>
<outxml>true</outxml>
<showWeaveInfo>false</showWeaveInfo>
<verbose>false</verbose>
<complianceLevel>${java.version}</complianceLevel>
<forceAjcCompile>true</forceAjcCompile>
<aspectLibraries>
<aspectLibrary>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</aspectLibrary>
</aspectLibraries>
<source>${java.version}</source>
<target>${java.version}</target>
<Xlint>ignore</Xlint>
</configuration>
</plugin>