2009-09-30 7 views
11

Câu hỏi này tương tự như trước one. Tôi cố gắng để @Autowire một phiên Hibernate trong một thử nghiệm mùa xuân-JUnit giao dịch của tôi, nhưng tôi nhận được ngoại lệ này:Cách thích hợp để autowire một Hibernate Session trong một giao dịch mùa xuân JUnit kiểm tra

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

Đây là lớp JUnit tôi:

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

Mỗi hoạt động tốt nếu tôi @Autowire a SessionFactory và nhận được Session lập trình của mình (thay vì xác định nó trong XML Mùa xuân) như sau:

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

tôi có thể, tuy nhiên, có ví dụ ban đầu của tôi để làm việc nếu tôi xác định tôi Session trong XML mùa xuân của tôi với <aop:scoped-proxy /> như vậy:

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

Câu hỏi của tôi là: Tại sao <aop:scoped-proxy /> cần thiết cho rằng có nên chỉ có một thread- ngữ cảnh giao dịch bị chặn trong thử nghiệm đơn vị của tôi? Điều gì cách thích hợp để xác định hạt đậu Hibernate Session của tôi?

Trả lời

6

SessionFactoryUtils.getSession() cũng tốt như bất kỳ cách nào khác để nhận phiên. Nó làm điều tương tự HibernateDaoSupport.getSession() sẽ làm.

Lý do bạn cần phạm vi proxy là do thời gian. Nếu không có phạm vi-proxy có vẻ như nó đang tiêm phiên trước khi thử nghiệm bắt đầu và do đó trước khi giao dịch bắt đầu và do đó bạn nhận được các lỗi.

Bằng cách thêm proxy phạm vi, proxy sẽ hỗ trợ phiên và chèn nó để không thực thi phiên trả trước thực tế (trước khi giao dịch bắt đầu) nhưng chỉ tìm nạp và thực hiện cuộc gọi khi thử nghiệm đang chạy. cần phải thực hiện một cuộc gọi chống lại nó.

4

Tôi nghĩ cách "đúng" là tiêm SessionFactory và tìm nạp phiên theo cách từ chương trình đó. Lý do mà bạn đang nhận được ngoại lệ là xuống đến hành vi tài liệu của SessionFactoryUtils.getSession():

Nhận một phiên Hibernate cho trao SessionFactory. Nhận thức và sẽ trả lại bất kỳ phiên bản nào hiện tại tương ứng Phiên ràng buộc với chuỗi hiện tại, ví dụ: khi sử dụng HibernateTransactionManager. Sẽ tạo Phiên mới nếu không, nếu "allowCreate" là đúng.

Vì không có gì đã ràng buộc phiên đối với giao dịch hiện tại nên không thành công.

Đề xuất của tôi sẽ sử dụng HibernateTemplate - xác định một trong ngữ cảnh của bạn và tự động điền vào thử nghiệm của bạn. HibernateTemplate có hầu hết các hoạt động giống như một phiên chiến tranh, nhưng phiên xử lý bit cho bạn. Bạn chỉ có thể thực hiện:

hibernateTemplate.get(User.class, "[email protected]"); 
+0

Cảm ơn bạn đã phản hồi. Nếu tôi đặt "allowCreate" thành true, Spring xuất hiện để tạo phiên cơ sở dữ liệu không giao dịch thứ hai, nghĩa là chú thích @Transactional không khôi phục các thay đổi của tôi trong khi thử nghiệm. Vấn đề với autowiring HibernateTemplate là tôi có các lớp DAO cấp phụ thuộc vào Session. Tôi đoán tôi có thể có họ phụ thuộc vào HibernateTemplate và sau đó làm một get (User.class ...) như bạn đề nghị. Tuy nhiên, tôi cảm thấy rằng tôi vi phạm Luật Demeter, cho rằng sự phụ thuộc thực sự của lớp DAO là Session và NOT HibernateTemplate. – 0sumgain

+0

DAO của bạn có được tiêm một phiên hay với SessionFactory không? Nếu bạn đang tiêm một phiên, bạn có thể muốn suy nghĩ lại, đó có thể không phải là một ý tưởng hay. – skaffman

+0

DAO được tiêm phiên. Bạn có thể giải thích tại sao đó không phải là một ý tưởng hay không? Cảm ơn. – 0sumgain