2012-03-21 4 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임을 알기위한 마커입니다.

스프링 콩 파일의 다음 구성에 따라 엔티티를 찾을 수 없습니다. 나는 DAO의 메소드에 대한 모든 발신자가 제대로 트랜잭션을 만드는 것이 있는지 확인하려면 이후

<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" /> 

나는

@Transactional(propagation=Propagation.MANDATORY) 

내 DAO를 표시했습니다.

나는 DAO를가 호출되는 모든 메소드에

@Transactional 

을 추가했습니다.

이 경우 예외가 발생합니다. 나는 DAO @Transactional 주석에서 전파 = Propagation.MANDATORY을 제거하면 EntityManager를 변경 내용을 플러시하려고 할 때

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

는 오류가 발생합니다.

모든 아이디어를 얻을 수 있습니다.

편집 스택의 모든 수준에서 제네릭을 사용하고 있습니다. 컨트롤러, 서비스 및 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 로의 모든 호출은 스프링 관리 빈을 전달합니다. 그게 당신이 의미 한 것입니까? –

+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를 사용하는 가정) : 통화가 프록시를 통해 갈 수 있도록 다른 빈에서 호출

<?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

죄송합니다. 나는이 일로 돌아 오기가 천천히 진행되었습니다. 나는 proxy-target-class = "true"를 사용할 수 있다고 생각하지 않는다. 왜냐하면 CGLIB가 제네릭 형식에 대해 불평하기 때문이다. –

+0

제네릭 유형 정보 cglib 2.2.2를 사용하고 있습니까? – fabdouglas