2010-09-08 39 views
0

我有一個交易問題,註釋一個服務,用@Transactional調用一個DAO拋出一個異常,說明會話未打開。我可以通過@Transactional註釋DAO來實現它的唯一方法。究竟會發生什麼?交易不工作,除非內部DAO

這是我想要做什麼,但不工作:

class CustomerService { 
    private CustomerDao dao; 

    @Transactional 
    public void foo() { 
     int customerId = dao.getCustomer("fred"); 
    } 
} 

class CustomerDao { 
    private HibernateTemplate hibernateTemplate; 

    public int getCustomer(String name) { 
     String sql = "SELECT {m.*} from Customers {m} where name=:name"; 
     Query qry = getSession().createSQLQuery(sql).addEntity("m", Customer.class); 
     qry.setParameter("name", name); 
     qry.setCacheable(false); 
     List<Customer> list = qry.list(); 
     return list.iterator().next().getId(); 
    } 

    private Session getSession() { 
     return hibernateTemplate.getSessionFactory().getCurrentSession(); 
    } 
} 

這是我在做什麼,而不是,但寧可不要到:

class CustomerService { 
    private CustomerDao dao; 

    public Customer(CustomerDao dao) { 
     this.dao = dao; 
    } 

    public void foo() { 
     int customerId = dao.getCustomer("fred"); 
    } 
} 

class CustomerDao { 
    private HibernateTemplate hibernateTemplate; 

    @Transactional 
    public int getCustomer(String name) { 
     String sql = "SELECT {m.*} from Customers {m} where name=:name"; 
     Query qry = getSession().createSQLQuery(sql).addEntity("m", Customer.class); 
     qry.setParameter("name", name); 
     qry.setCacheable(false); 
     List<Customer> list = qry.list(); 
     return list.iterator().next().getId(); 
    } 

    private Session getSession() { 
     return hibernateTemplate.getSessionFactory().getCurrentSession(); 
    } 
} 

問題似乎是由CustomerService在包裝類的構造函數中實例化引起的,其中包裝在Spring xml上下文文件中聲明:

class AllServices { 
    private final CustomerService customerService; 
    private final OrderService orderService; 

    @Autowired 
    public AllServices(CustomerDao customerDao, OrderDao orderDao) { 
     this.customerService = new CustomerService(customerDao); 
     this.orderService = new OrderService(orderDao); 
    } 

    public CustomerService getCustomerService() { 
     return this.customerService; 
    } 

    public OrderService getOrderService() { 
     return this.orderService; 
    } 
} 

彈簧文件看起來是這樣的:

<context:annotation-config /> 
<import resource="classpath:db-spring-conf.xml"/> 
<bean id="allServices" class="myPackage.AllServices" /> 

和DB-彈簧的conf:

<bean id="editorDatasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
    <property name="driverClassName" value="com.mysql.jdbc.Driver" /> 
    <property name="url" value="${versioning.db}" /> 
    <property name="username" value="${versioning.user}" /> 
    <property name="password" value="${versioning.pass}" /> 
</bean> 

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

<bean id="editorSessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> 
    <property name="dataSource" ref="editorDatasource"/> 
    <property name="exposeTransactionAwareSessionFactory"> 
     <value>true</value> 
    </property> 
    <property name="annotatedClasses"> 
     <list> 
      <value>myPackage.Order</value> 
     </list> 
    </property> 
    <property name="mappingResources"> 
     <list> 
      <value>mappings/customer.hbm.xml</value> 
     </list> 
    </property> 
    <property name="hibernateProperties"> 
     <props> 
      <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> 
      <prop key="hibernate.show_sql">true</prop> 
      <prop key="hibernate.hbm2ddl.auto">validate</prop> 
      <!-- Enable Query Cache --> 
      <prop key="hibernate.cache.use_query_cache">false</prop> 
      <!-- Enable 2nd Level Cache --> 
      <prop key="hibernate.cache.use_second_level_cache">false</prop> 
      <prop key="hibernate.connection.autocommit">false</prop> 
      <prop key="hibernate.current_session_context_class">org.springframework.orm.hibernate3.SpringSessionContext</prop> 
     </props> 
    </property> 
</bean> 

<bean id="editorHibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate"> 
    <property name="sessionFactory" ref="editorSessionFactory"/> 
</bean> 

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

<!-- DAOs --> 
<bean id="customerDao" class="myPackage.CustomerHibernateDao" /> 
<bean id="orderDao" class="myPackage.OrderHibernateDao" /> 

現在我已經感動的CustomerService的實例到Spring配置文件和一切工作的對待。所有使用@Transactional的類都必須位於上下文文件中嗎?另外,爲了使工作我不得不創建的CustomerService接口,以防止異常,同時加載上下文文件 - Could not generate CGLIB subclass of class

+0

也許交易方面不適用於'CustomerService'。顯示它是如何配置的。 – axtavt 2010-09-08 17:13:30

+0

請顯示您的spring xml配置 – Vadeg 2010-09-08 17:47:34

回答

2

所以,你確定了問題的原因 - Spring的@Transactional支持是一個方面,而在春季方面僅適用於Spring承包商管理的組件(雖然它是can be changed,但它是複雜案例的高級功能)。

如果你不喜歡在XML聲明服務,你可以看看其他選項delcare Spring管理組件:

關於CGLIB代理的問題,請參閱7.6 Proxying mechanisms - 可能您在類路徑中沒有CGLIB實現。