복붙노트

[SPRING] 선언적인 트랜잭션 (@Transactional)은 Spring의 @Repository와 작동하지 않습니다.

SPRING

선언적인 트랜잭션 (@Transactional)은 Spring의 @Repository와 작동하지 않습니다.

스프링, JPA 및 임베디드 H2 데이터베이스를 사용하여 간단한 응용 프로그램을 만들려고합니다. 최근에는 선언적 트랜잭션에 대해이 이상한 문제가 발생했습니다. DAO에 @Repository annotation을 autowire하면 그들은 커밋하지 않습니다. 더 구체적으로 나는 flush에 대한 예외를 얻는다 :

javax.persistence.TransactionRequiredException: 
Exception Description: No transaction is currently active

여기 내 설정입니다 :

<persistence-unit name="schedulePU" transaction-type="RESOURCE_LOCAL">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <properties>
        <property name="javax.persistence.jdbc.driver" value="org.h2.Driver" />
        <property name="javax.persistence.jdbc.url" value="jdbc:h2:~/scheduleDB" />
        <property name="javax.persistence.jdbc.user" value="sa" />
        <property name="javax.persistence.jdbc.password" value="" />
        <property name="eclipselink.target-database" value="org.eclipse.persistence.platform.database.H2Platform" />
        <property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
        <property name="eclipselink.logging.level" value="FINE"/>
    </properties>
</persistence-unit>
@Entity
@Table(name = "Professors")
public class Professor {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String name;

    public Professor() { }

    public Professor(String name) {
        this.name = name;
    }
}
@Repository
public class JpaDao {

    @PersistenceContext
    private EntityManager em;

    @Transactional
    public void addProfessor(Professor professor) {
        em.persist(professor);
        em.flush();
    }
}
<beans>
    <context:component-scan base-package="com.spybot.schedule.dao" />

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

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="schedulePU" />
    </bean>

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

    <tx:annotation-driven transaction-manager="transactionManager" />
</beans>
@Controller
public class HomeController {

    @Inject
    JpaDao dao;

    @RequestMapping("/add")
    public @ResponseBody String add(String name) {
        Professor p = new Professor(name);
        dao.addProfessor(p);
        return ":)";
    }
}

그리고 지금은 흥미로운 부분입니다. DAO에서 @Repository 주석을 제거하고 database.xml에 명시 적으로 지정하면 모든 것이 정상적으로 작동합니다.

또 다른 을 스프링 서블릿 config에 넣으면 문제가 해결되지만 그 이유는 무엇입니까?

해결법

  1. ==============================

    1.아마도 spring-servlet.xml의 component-scan은 DAO 클래스를 스캐닝에 포함하고 있기 때문에 애플리케이션 컨텍스트 ( "database"가 아닌)에서 인스턴스를 생성하기 때문에 ... 웹에서 이들을 액세스 할 때 DAO는 웹 컨트롤러에서 비 트랜잭션 버전을 액세스하고 있습니다 (해당 tx : annotation-driven 태그를 추가하지 않는 한).

    아마도 spring-servlet.xml의 component-scan은 DAO 클래스를 스캐닝에 포함하고 있기 때문에 애플리케이션 컨텍스트 ( "database"가 아닌)에서 인스턴스를 생성하기 때문에 ... 웹에서 이들을 액세스 할 때 DAO는 웹 컨트롤러에서 비 트랜잭션 버전을 액세스하고 있습니다 (해당 tx : annotation-driven 태그를 추가하지 않는 한).

    따라서이 태그를 추가하는 것은 실제로 잘못된 응용 프로그램 컨텍스트에 DAO 인스턴스를 생성하기 때문에 나쁜 솔루션입니다. 웹 레이어 구성 요소 생성에보다 세부적인 기본 패키지 구성을 만드는 것이 좋습니다.

    내 봄 - servlet.xml에서 가 @Controller 클래스 만 검사한다고 생각했기 때문에이 동일한 문제가 발생했지만 아니요 .-(

  2. ==============================

    2.그냥 짐작 하긴하지만, 이 자동으로 등록되기 때문에 자신의 PersistenceAnnotationBeanPostProcessor를 등록 할 필요가 없습니다. 두 사람이 서로를 방해 할 수도 있습니다.

    그냥 짐작 하긴하지만, 이 자동으로 등록되기 때문에 자신의 PersistenceAnnotationBeanPostProcessor를 등록 할 필요가 없습니다. 두 사람이 서로를 방해 할 수도 있습니다.

    내가 말했듯이, 단지, 직감.

  3. ==============================

    3.@Transactional 어노테이션은 인터페이스 정의, 인터페이스의 메소드, 클래스 정의 또는 클래스의 public 메소드 앞에 위치 할 수 있습니다. 그러나 @Transactional 주석의 단순한 존재만으로는 실제로 트랜잭션 동작을 수행 할만큼 충분하지 않습니다. @Transactional 주석은 @ Transactional-aware 인 메타 데이터를 사용할 수있는 단순한 메타 데이터입니다. 트랜잭션 비헤이비어로 적절한 Bean을 구성하십시오. 위의 예제의 경우 트랜잭션 동작을 전환하는 것은 요소의 존재입니다.

    @Transactional 어노테이션은 인터페이스 정의, 인터페이스의 메소드, 클래스 정의 또는 클래스의 public 메소드 앞에 위치 할 수 있습니다. 그러나 @Transactional 주석의 단순한 존재만으로는 실제로 트랜잭션 동작을 수행 할만큼 충분하지 않습니다. @Transactional 주석은 @ Transactional-aware 인 메타 데이터를 사용할 수있는 단순한 메타 데이터입니다. 트랜잭션 비헤이비어로 적절한 Bean을 구성하십시오. 위의 예제의 경우 트랜잭션 동작을 전환하는 것은 요소의 존재입니다.

    스프링 문서 http://static.springsource.org/spring/docs/2.0.8/reference/transaction.html

  4. from https://stackoverflow.com/questions/9051721/declarative-transactions-transactional-doesnt-work-with-repository-in-sprin by cc-by-sa and MIT license