복붙노트

[SPRING] Spring 트랜잭션 JUnit 테스트에서 Hibernate Session을 autowire하는 적절한 방법

SPRING

Spring 트랜잭션 JUnit 테스트에서 Hibernate Session을 autowire하는 적절한 방법

이 질문은 이전 질문과 비슷합니다. 내 Spring-JUnit-Transactional 테스트 중 하나에서 @AutowireHibernate Session을 시도하고 있지만이 예외가 발생한다.

java.lang.IllegalStateException : 하이버 네이트 세션이 쓰레드에 바인드되지 않았으며, 컨피규레이션은 비 트랜잭션 (non-transactional) 생성을 허용하지 않는다.

다음은 JUnit 클래스입니다.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"/applicationContext.xml"})
@TransactionConfiguration(transactionManager="transactionManager")
@Transactional
public class MyTest {
    @Qualifier("session")
    @Autowired
    private Session session;

    @Test
    public void testSomething() {
        session.get(User.class, "me@here.com");
    }
}

@ SessionFactory를 호출하고 프로그래밍 방식으로 (Spring XML에서 정의하는 대신) 내 Session을 얻는다면 모든 것이 잘 작동한다.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"/applicationContext.xml"})
@TransactionConfiguration(transactionManager="transactionManager")
@Transactional
public class MyTest{    
    @Qualifier("sessionFactory")
    @Autowired
    private SessionFactory sessionFactory;

    @Test
    public void testSomething() {
    Session session = SessionFactoryUtils.getSession(sessionFactory, false);
        session.get(User.class, "me@here.com");
    }
}

그러나 Spring XML에서 를 사용하여 Session을 정의한 경우 원래 예제를 사용할 수 있습니다.

<?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:tx="http://www.springframework.org/schema/tx"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
        ">

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
        ...
    </bean>

    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="configLocation"><value>classpath:/hibernate.cfg.xml</value></property>
        <property name="configurationClass">
            <value>org.hibernate.cfg.AnnotationConfiguration</value>
        </property>
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
        <property name="dataSource" ref="dataSource" />
    </bean>

    <tx:annotation-driven transaction-manager="transactionManager"/>

    <bean id="session" class="org.springframework.orm.hibernate3.SessionFactoryUtils" factory-method="getSession" scope="prototype">
        <constructor-arg ref="sessionFactory" />
        <constructor-arg value="false" />
        <!-- This is seems to be needed to get rid of the 'No Hibernate Session' error' -->
        <aop:scoped-proxy />
    </bean>
</beans>

제 질문은 : 단원 테스트에서 단 하나의 스레드 - 바운드 트랜잭션 컨텍스트가 있어야한다는 이유로 가 필요한 이유는 무엇입니까? 내 Hibernate Session bean을 정의하는 적절한 방법은 무엇입니까?

해결법

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

    1.SessionFactoryUtils.getSession ()은 세션을 가져 오는 다른 방법과 같습니다. HibernateDaoSupport.getSession ()이하는 것과 같은 일을한다.

    SessionFactoryUtils.getSession ()은 세션을 가져 오는 다른 방법과 같습니다. HibernateDaoSupport.getSession ()이하는 것과 같은 일을한다.

    범위 프록시가 필요한 이유는 타이밍 때문입니다. Scoped-proxy가 없다면 테스트가 시작되기 전에 Session이 삽입되고 있으므로 트랜잭션이 시작되기 전에 오류가 발생합니다.

    scoped-proxy를 추가함으로써 Session을 프록시하고 주입하므로 트랜잭션이 시작되기 전에 (세션이 시작되기 전에) 실제 세션을 주입하지 않고 테스트가 실행되면 실제로 세션을 가져 와서 호출합니다. 그것을 부르십시오.

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

    2.나는 "적절한"방법은 SessionFactory의 주입이며, Session에서 Session을 가져 오는 것이라고 생각한다. 예외가 발생하는 이유는 문서화 된 SessionFactoryUtils.getSession ()의 동작 때문입니다.

    나는 "적절한"방법은 SessionFactory의 주입이며, Session에서 Session을 가져 오는 것이라고 생각한다. 예외가 발생하는 이유는 문서화 된 SessionFactoryUtils.getSession ()의 동작 때문입니다.

    현재 트랜잭션에 세션을 바인드하지 않았으므로 실패합니다.

    제 제안은 HibernateTemplate을 사용하는 것입니다 - 당신의 컨텍스트에서 하나를 정의하고 테스트에 그것을 자동으로 연결합니다. HibernateTemplate은 war 세션과 거의 같은 오퍼레이션을 가지고 있지만, 당신을 위해 세션 처리 비트를 수행한다. 당신은 할 수 있어야합니다 :

    hibernateTemplate.get(User.class, "me@here.com");
    
  3. from https://stackoverflow.com/questions/1500775/proper-way-to-autowire-a-hibernate-session-in-a-spring-transaction-junit-test by cc-by-sa and MIT license