Korrekt måde at autowire en Dvale Session i Foråret Transaktionen JUnit test

Dette spørgsmål svarer til en tidligere en. Jeg forsøger at @Autowire en Dvale Session i et af mine Forårs-JUnit-Transaktionsrelaterede test, men jeg får denne undtagelse:

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

Her er min JUnit klasse:

@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]");
    }
}

Alle virker fint, hvis jeg @Autowire en SessionFactory og få min Session ved hjælp af programmering (i stedet for at definere det i Foråret XML) som så:

@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]");
    }
}

Kan jeg dog få min oprindelige eksempel, til at arbejde, hvis jeg definere min Session i min Foråret, XML med <aop:scoped-proxy /> som så:

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

Mit spørgsmål er: Hvorfor er <aop:scoped-proxy /> behov for i betragtning af, at der kun skal én tråd-afgrænset transaktion sammenhæng i min enhed? Hvad er den rigtige måde at definere min Hibernate Session bean?

OriginalForfatteren 0sumgain | 2009-09-30

2 svar

  1. 6

    SessionFactoryUtils.getSession() er så god som enhver anden måde at få den Session. Det gør de samme ting HibernateDaoSupport.getSession() ville gøre.

    Grunden til at du skal virkefelter-proxy er på grund af timingen. Uden virkefelter-proxy-det ser ud til, at det er ved at fixe den Session, før prøven begynder, og dermed før transaktionen påbegyndes, og så får du fejl.

    Ved at tilføje virkefelter-proxy-det fuldmagter Session og sprøjter, så det ikke injicere den faktiske session upfront (før transaktionen starter), men kun henter det, og gør opfordrer på det, når testen kører, når det faktisk har brug for at foretage et opkald imod det.

    OriginalForfatteren Michael Wiles

  2. 4

    Jeg tror, at den “rigtige” måde, er injektion af SessionFactory, og programmatisk at hente den Session fra det. Grunden til, at du får den undtagelse, er ned til de dokumenterede adfærd SessionFactoryUtils.getSession():

    Få en Dvale Session for den givne
    SessionFactory. Er opmærksom på og vil
    returnere enhver gældende tilsvarende
    Session bundet til den aktuelle tråd,
    for eksempel, når du bruger
    HibernateTransactionManager. Vil
    oprette en ny Session på anden måde, hvis
    “allowCreate” er sandt.

    Da intet har bundet en session til den aktuelle transaktion, er det ikke.

    Mit forslag ville være at bruge HibernateTemplate – angiv ét i din sammenhæng, og autowire det ind i din test. HibernateTemplate har de fleste af de samme operationer som en krig Session, men det gør den session håndtering smule for dig. Du skal bare være i stand til at gøre:

    hibernateTemplate.get(User.class, "[email protected]");
    Tak for svaret. Hvis jeg set “allowCreate” true”, Foråret ser ud til at skabe en anden ikke-transaktionsrelaterede database session, det vil sige, @Transaktionsbeslutning annotation ikke rollback mine ændringer under test. Problemet med autowiring en HibernateTemplate er, at jeg har DAO-niveau-klasser, der er afhængige af Session. Jeg tror, jeg kunne have dem afhængige af HibernateTemplate og derefter gøre et får(User.class …) som du foreslog. Men jeg føler, at jeg overtræder Loven om Demeter, givet at den sande afhængighed af DAO klasse er-Session, og IKKE HibernateTemplate.
    Er din DAOs injiceres med en Session, eller med en SessionFactory? Hvis du sprøjter i en Session, vil du sandsynligvis til at genoverveje, om det er nok ikke en god idé.
    DAOs injiceres med Session. Kan du forklare, hvorfor det ikke en god idé? Tak.
    Fordi Session er en kortvarig objekt, og at du generelt ikke injicere kortvarig objekter kan lide det.
    Tak for svar igen. Ja, det er sandt, men jeg har min Session objekter scoped som “anmodning”, som i Foråret skal afslutte Sessionen i slutningen af hvert HTTP-anmodning.

    OriginalForfatteren skaffman

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *