本文介绍了在Spring Transaction JUnit测试中自动装入Hibernate Session的正确方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题与之前的一个。我试图在我的一个Spring-JUnit-Transactional测试中对 @Autowire 一个Hibernate Session进行测试,但我得到这个异常:



java.lang.IllegalStateException:没有Hibernate Session绑定到线程,并且配置不允许创建非事务性...

$ b $
$ b

这是我的JUnit类: ContextConfiguration(locations = {/ applicationContext.xml})
@TransactionConfiguration(transactionManager =transactionManager)
@Transactional
public class MyTest {
@Qualifier(session )
@Autowired
私有会话会话;

@Test
public void testSomething(){
session.get(User.class,[email protected]);




$ b

如果我 @Autowire a SessionFactory 并以编程方式获取我的 Session (而不是在Spring中定义它) XML)如下所示:

$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ @ $ @ $ @ 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,[email protected]);


$ / code>

然而,我可以让我原来的例子工作如果我使用< aop:scoped-proxy /> 在我的Spring XML中定义我的 Session / p>

 <?xml version =1.0encoding =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 =dataSourceclass =com.mchange.v2.c3p0.ComboPooledDataSourcedestroy-method =close>
...
< / bean>

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

< bean id =transactionManagerclass =org.springframework.orm.hibernate3.HibernateTransactionManager>
< property name =sessionFactoryref =sessionFactory/>
< property name =dataSourceref =dataSource/>
< / bean>

< tx:注解驱动的事务管理器=transactionManager/>

< bean id =sessionclass =org.springframework.orm.hibernate3.SessionFactoryUtilsfactory-method =getSessionscope =prototype>
< constructor-arg ref =sessionFactory/>
< constructor-arg value =false/>
< aop:scoped-proxy />
< / bean>
< / beans>

我的问题是:为什么< aop:scoped-proxy /> ; 需要在我的单元测试中应该只有一个线程限制的事务上下文? 定义我的 Hibernate Session bean的正确方法

解决方案

SessionFactoryUtils.getSession()与获取会话的其他方式一样好。它和HibernateDaoSupport.getSession()所做的一样。



您需要scoped-proxy的原因是因为时机。如果没有scoped-proxy,它似乎是在测试开始之前注入Session,从而在事务开始之前注入Session,所以你会得到错误。



通过添加scoped-代理它代理会话并注入它,因此它不会在事务开始前预先注入实际会话,而只是在测试运行时才提取它并对其进行调用,而实际上它需要对它进行调用。 / p>

This question is similar to a previous one. I am trying to @Autowire a Hibernate Session in one of my Spring-JUnit-Transactional tests but I am getting this exception:

java.lang.IllegalStateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional ...

Here is my JUnit class:

@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, "[email protected]");
    }
}

Every works fine if I @Autowire a SessionFactory and get my Session programmatically (instead of defining it in the Spring XML) like so:

@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, "[email protected]");
    }
}

I can, however, get my original example to work if I define my Session in my Spring XML with <aop:scoped-proxy /> like so:

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

My question is: Why is <aop:scoped-proxy /> needed given that there should only one thread-bounded transaction context in my unit test? What is the proper way to define my Hibernate Session bean?

解决方案

SessionFactoryUtils.getSession() is as good as any other way of getting the Session. It does the same thing HibernateDaoSupport.getSession() would do.

The reason you need scoped-proxy is because of timing. Without the scoped-proxy it seems that it is injecting the Session before the test begins and thus before the transaction begins and so you get the errors.

By adding the scoped-proxy it proxies the Session and injects that so it does not inject the actual session upfront (before the transaction starts) but only fetches it and makes calls on it once the test is running, when it actually needs to make a call against it.

这篇关于在Spring Transaction JUnit测试中自动装入Hibernate Session的正确方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-12 01:29