2

Spring の @Transactional や @Configurable などのアノテーションをサポートするために、コンパイル時の織りで aspectj を使用しようとしています。私は 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]

そのため、テーブルごとの休止状態シーケンスは更新されますが、私のエンティティはデータベースに挿入されません。

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でエクスポートされた Web サービスから saveOrUpdate メソッドを呼び出します。

PS: また、私の 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" />

すべてがまともに見えますが、これが機能しない理由の答えが見つかりません...

4

3 に答える 3

3

このリンクをたどって答えを見つけました: http://forum.springsource.org/showthread.php?18953-DispatcherServlet-and-ContextLoaderListener

この問題は、Spring MVC も使用していて、ほぼ同一の 2 つの Spring コンテキストを知らずに作成していたことが原因でした。したがって、トランザクションは最初のコンテキスト (JAX-WS 呼び出しを受け取るもの) のトランザクション マネージャーによって管理されましたが、呼び出していたエンティティ マネージャーは 2 番目のコンテキスト (別のトランザクション マネージャー) によって管理されていました。

解決策は、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 注釈付き) を使用したため、「サーブレット」コンテキストでのコンポーネントスキャンの基本パッケージのコンテキストのスコープも縮小する必要がありました。

以下は、私の一日を救ったリンクからの引用です。

DispatcherServlet は常に -servlet.xml を使用して独自の構成ファイルをロードします。このファイルには、Controllers、ViewResolvers、LocaleResolvers などの Web コンポーネントが含まれますが、中間層コンポーネントは含まれません。

次に ContextLoaderListener を使用して、中間層およびデータ層コンポーネントを含むファイルをロードします。Spring は、これらすべてのコンポーネントを ApplicationContext にマージして、Web 層コンポーネントから中間層コンポーネントにアクセスできるようにします。>Rob Harrop リード エンジニア、dm サーバー

于 2012-03-24T23:50:43.067 に答える
0

EntityManagerを使用する場合、コード内の休止状態の問題に対処する必要はありません。それがまさにjpaの目的です。

私はしばらく前に同じ問題を抱えていました。

EntityManagerには@PersistenceContextを注入する必要があります。getEntityManager()は実行しません。

また、注釈付き関数は公開されている必要があります。

于 2012-02-03T19:03:39.887 に答える
0

そのため、テーブルごとの休止状態シーケンスは更新されますが、私のエンティティはデータベースに挿入されません。

2 つの同一の 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>
于 2014-11-08T05:03:12.360 に答える