2012-03-21 1 views
0

Tomcat内でSpringでJPAを使用しようとしていて、トランザクションが期待通りに開始されないという問題があります。TomcatでSpringとJPAを使用してトランザクションを開始しない

私は、Hibernate 3.6.9.Final、Spring 3.0.5.RELEASEを使用しており、Tomcat 6.0.30で動作しています。

私は、エンティティとデータアクセスオブジェクトを含む別個のデータアクセス用のjarファイルを持っています。このjarには、次の内容のMETA-INF/persistence.xmlファイルが含まれています。

<persistence xmlns="http://java.sun.com/xml/ns/persistence" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" 
      version="2.0"> 
    <persistence-unit name="osPU"> 
     <provider>org.hibernate.ejb.HibernatePersistence</provider> 
    </persistence-unit> 
</persistence> 

これはわかりますが、これは非常に単純で、実際にはJPAがJPAエンティティを含むjarであることを知るためのマーカーです。

エンティティは、春のbeansファイルの次の設定に基づいてOKです。

<tx:annotation-driven /> 

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
    <property name="dataSource" ref="dataSource" /> 
    <property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml" /> 
    <property name="jpaProperties"> 
     <props> 
      <prop key="hibernate.dialect">${database.dialect}</prop> 
      <prop key="hibernate.show_sql">${database.show.sql}</prop> 
      <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop> 
     </props> 
    </property> 
</bean> 

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" > 
    <property name="entityManagerFactory" ref="entityManagerFactory" /> 
</bean> 

<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" /> 

私はDAOのメソッドへのすべての発信者が適切にトランザクションを作成することを確認するため、私は

@Transactional(propagation=Propagation.MANDATORY) 

と私のDAOをマークしました。

私はDAOにはから呼び出されるすべてのメソッドに

@Transactional 

を追加しました。

この結果、例外が発生します。

org.springframework.transaction.IllegalTransactionStateException: No existing transaction found for transaction marked with propagation 'mandatory' 

私はDAO @Transactional注釈から伝播= Propagation.MANDATORYを削除した場合のEntityManagerが変更をフラッシュしようとしたとき、私はエラーを取得します。

すべてのアイデアをいただければ幸いです。

EDIT私はスタック内のすべてのレベルでGenericsを使用しています。コントローラ、サービス、およびDAO。 Springがメソッド呼び出しをインターセプトしてトランザクションでラップすることができないため、これが問題を引き起こしているかどうかは不明です。

public abstract class AbstractEavDefinitionController<DTO> implements EAVDefinitionOperations<DTO> { 

    private EavDefinitionService<DTO> eavDefinitionService; 

    private Validator<DTO> validator; 

    @RequestMapping(method = RequestMethod.POST) 
    @ResponseBody 
    public ServiceResult<Long> save(@RequestBody DTO dto) { 
     ValidationResult<DTO> validationResult = validator.validate(dto); 

     if (validationResult.isValid()) { 
      Long result = eavDefinitionService.save(dto); 
      return new SimpleServiceResult<Long>(result); 
     } 

     return new SimpleServiceResult<Long>(validationResult); 
    } 
} 

バリやアクティブなトランザクションを持っている必要があり、サービス利用のDAO両方:ここ

詳細は、コントローラのコードです。バリデータ呼び出しは期待どおりに動作し、DB呼び出しを行うことができます。サービスへの呼び出しがスローされます

javax.persistence.TransactionRequiredException: no transaction is in progress 

私が理解できないのは、DAOへの呼び出しが成功したが、次の呼び出しが失敗することです。トランザクションを使用するときにコントローラコール内で開くことができるトランザクションの数には制限がありますか?

+0

注釈を付けている方法を? – mrembisz

+0

コントローラからDAOへのすべての呼び出しは、スプリングマネージドBeanを経由します。それはあなたが意味することですか? –

+0

いいえ、トランザクションコントローラメソッドがどのように呼び出されるかが重要です。コントローラメソッド呼び出しがプロキシを経由する場合にのみ、必要なトランザクションが開始されます。 – mrembisz

答えて

0

ジェームズ、私が過去に取ったアプローチは以下の通りです。 非常に基本的な永続性。XML:

<persistence-unit name="audit"> 
<!-- dont need props here as configured in Spring --> 

<properties> 

</properties> 

</persistence-unit> 

そして、次のように私の春のコンテキストがアップ配線された(データソース定義を除外):

<tx:annotation-driven/> 
<context:annotation-config/> 


<bean id="jpaAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> 
    <property name="databasePlatform" value="${db.dialect}"/> 
    <property name="showSql" value="true"/> 
    <property name="generateDdl" value="false"/> 
</bean> 


<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
    <property name="persistenceUnitName" value="audit"/> 
    <property name="dataSource" ref="datasource"/> 
<property name="jpaVendorAdapter" ref="jpaAdapter"/> 
<property name="jpaProperties"> 
    <props> 
      <prop key="hibernate.generate_statistics">true</prop> 
     </props> 
</property> 
</bean> 

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
    <property name="entityManagerFactory" ref="entityManagerFactory"/> 
</bean> 


<bean id="auditDAO" class="com.gridfreak.core.audit.persistence.JPAAuditDAO"/> 

そして、私の実際のDAOクラスでは、単に永続コンテキストとマークメソッドのトランザクションを注入:

public class JPAAuditDAO implements AuditDAO { 

@PersistenceContext(unitName="audit") 
private EntityManager entityManager = null; 


@Transactional(propagation = Propagation.REQUIRED) 
public List<VarAudit> findByPiid(long piid) { 
     //... 
    } 

    //.... 
} 

これはほんの一例であり、トランザクション発信の責任を含むサービスに委任していませんでした。トランザクションを必須ではなくREQUIREDとしてマークし、それらが作成されているかどうかを確認しましたが、その場合はサービスBean自体のトランザクションアノテーションの問題が発生している可能性があります。

アダム

1

私が推測すると、DAOの呼び出し元が別のスプリングベースのコンポーネントによって呼び出されるインタフェースに基づいていない(@Controller?、JAX-RSリソース?単純なクラス豆、...) だから、このクラス@Autowiredフィールドをうまく管理しても、@Transactional操作呼び出しはSpringによって傍受されません。設定は、あなたの問題を解決するために (あなたがあなたのコンテキストでLTWを使用していると仮定):呼び出しがそのプロキシ経由で行くことができますので、別のBeanから呼び出さ

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:util="http://www.springframework.org/schema/util" xmlns:repository="http://www.springframework.org/schema/data/repository" 
    xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:task="http://www.springframework.org/schema/task" 
    xmlns:jpa="http://www.springframework.org/schema/data/jpa" 
    xsi:schemaLocation=" 
      http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd 
      http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
      http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd 
      http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd 
      http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd 
      http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd 
      http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd 
      http://www.springframework.org/schema/data/repository 
      http://www.springframework.org/schema/data/repository/spring-repository.xsd 
      http://www.springframework.org/schema/data/jpa 
      http://www.springframework.org/schema/data/jpa/spring-jpa.xsd" 
    default-autowire="byName"> 

    <context:load-time-weaver /> 
    <context:spring-configured /> 
    <context:annotation-config /> 
    <aop:aspectj-autoproxy /> 

    <bean name="loadTimeWeaver" class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" /> 
    <context:component-scan base-package="com.mycompany.mypackage" /> 

    <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/> 
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
     <property name="dataSource" ref="dataSource" /> 
     <property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml" /> 
     <property name="jpaProperties"> 
      <props> 
       <prop key="hibernate.dialect">${database.dialect}</prop> 
       <prop key="hibernate.show_sql">${database.show.sql}</prop> 
       <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop> 
      </props> 
     </property> 
    </bean> 
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" 
     p:entityManagerFactory-ref="entityManagerFactory" /> 
    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" /> 
    <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" /> 
</beans> 
+0

申し訳ありませんが、私はこれに戻ってゆっくりしてきました。 CGLIBはジェネリック型について不平を言っているので、私はproxy-target-class = "true"を使うことはできません。 –

+0

ジェネリックタイプについてcglib 2.2.2を使用していますか? – fabdouglas

関連する問題