2011-10-14 65 views
3

所以我的春季教育仍在繼續。目前,我正在嘗試學習一些註釋和它們爲Spring 3帶來的東西。因此,我有一個迷你web應用程序,可以連接到數據庫並通過表單輸入內容並顯示記錄等。一切正常。我決定嘗試讓Spring自動檢測我標記爲@Transactional的服務bean,但這樣做會阻止應用程序保存到數據庫。所以:Spring @Transactional不能與其他註釋一起使用?

@Transactional 
public class ReservationServiceImpl implements ReservationService { 

有效。我在springcourt-data.xml文件中有這個類的bean聲明。沒問題。當我這樣做雖然:

@Transacational 
@Service("reservationService") 
public class ReservationServiceImpl implements ReservationService { 

它不再起作用。我確實在springcourt-servlet.xml文件中有

<context:component-scan base-package="com.springcourt" /> 

。那麼誰能告訴我我搞砸了什麼?我所做的只是爲該類添加另一個註釋,並從xml文件中移除該bean定義,並且不再將數據保存到數據庫。我仍然可以從數據庫查詢記錄和內容,但顯然它使用自動檢測的服務bean。

下面是配置文件:

springcourt-servlet.xml 
<beans xmlns="http://www.springframework.org/schema/beans" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:context="http://www.springframework.org/schema/context" 
xmlns:mvc="http://www.springframework.org/schema/mvc" 
xsi:schemaLocation=" 
    http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.0.xsd 
    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> 

<context:component-scan base-package="com.springcourt" /> 

<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" /> 

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> 
    <property name="webBindingInitializer"> 
     <bean class="com.springcourt.web.ReservationBindingInitializer" /> 
    </property> 
</bean> 

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 
    <property name="prefix" value="/WEB-INF/jsp/"/> 
    <property name="suffix" value=".jsp"/> 
</bean> 
</beans> 

和:

springcourt-data.xml 
<beans xmlns="http://www.springframework.org/schema/beans" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:aop="http://www.springframework.org/schema/aop" 
xmlns:tx="http://www.springframework.org/schema/tx" 
xmlns:p="http://www.springframework.org/schema/p" 
xsi:schemaLocation=" 
http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
http://www.springframework.org/schema/tx 
http://www.springframework.org/schema/tx/spring-tx-2.0.xsd 
http://www.springframework.org/schema/aop 
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"> 

<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" /> 

<bean id="entityManagerFactory" 
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
    <property name="dataSource" ref="dataSource" /> 
    <property name="jpaVendorAdapter"> 
     <bean 
      class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> 
      <property name="database" value="MYSQL" /> 
      <property name="showSql" value="true" /> 
     </bean> 
    </property> 
</bean> 

<bean id="dataSource" 
     class="org.apache.commons.dbcp.BasicDataSource"> 
    <property name="driverClassName" value="com.mysql.jdbc.Driver" /> 
    <property name="url" value="jdbc:mysql://localhost:3306/test" /> 
    <property name="username" value="root" /> 
    <property name="password" value="admin" /> 
    <property name="initialSize" value="5" /> 
</bean> 

<bean id="transactionManager" 
    class="org.springframework.orm.jpa.JpaTransactionManager"> 
    <property name="entityManagerFactory" ref="entityManagerFactory" /> 
</bean> 

<tx:annotation-driven /> 

<bean id="reservationService" class="com.springcourt.service.ReservationServiceImpl"/> 
</beans> 
+0

幾件事情你爲什麼要在上下文中聲明reservationService並標註它@服務,也是上下文組件掃描添加到第二個方面在您發佈的「And」後列出的文件。 –

+0

您在「@Transacational」中有錯字。將它改正爲「@Transactional」 – buddamus

回答

3

當你使用@Service和組件掃描,bean由調度程序servlet(mvc)創建的上下文創建。由於事務:註解驅動是在根應用程序上下文中定義的,因此它不適用於servlet上下文中的bean。您可以通過刪除@Service並將bean定義移動到servlet上下文文件來驗證 - 您應該看到相同的結果。

當您不使用組件掃描時 - 在根應用程序上下文的XML中定義bean。

解決的辦法是更改Web圖層中的組件掃描標記以僅包含Web圖層類 - 可以使用不同的基本包或使用包含/排除過濾器。在其他bean的根應用程序上下文中添加另一個組件掃描。

查詢可能正在工作,因爲您可能配置了OpenEntityManagerInViewInterceptor/Filter。

+0

不,不需要OpenEntityManagerInViewInterceptor。至少不是我明確宣佈的。但是,我試圖說出你的看法,而且似乎已經奏效。我在spring-court-data.xml文件中爲服務包聲明瞭組件掃描標籤,並將其他文件保存在spring-court-servlet.xml文件中。有點像Prasanna Talakanti在上面說我猜。我顯然不完全理解這些文件的分離如何影響不同的標籤。 – cardician

+0

再一次評論。我從spring-court - *。xml文件中刪除了所有配置,並將其放入applicationContext.xml中,然後回到僅使用並且事情正常工作。所以這個問題肯定是與這兩個文件之間的事情是如何分開的。如果任何人都可以指出我對這個層次結構如何工作的清晰解釋,我將不勝感激,謝謝。 – cardician

+0

請參閱spring mvc文檔的第13.2節 - http://static.springsource.org/spring/docs/2.5.x/reference/mvc.html。將所有內容放在一個文件中 - 但不推薦。 – gkamal

1

既然你可以通過同一個bean查詢數據庫,您的@Transactional的作品,或者你經常會得到一個異常(至少休眠)。最有可能在保存操作中,您會得到一些導致事務回滾的運行時異常。試着找出什麼是例外,然後從那裏去。


更新

要查看是否@Transactional得到了應用,打印堆棧跟蹤從方法內部。如果你看到很多事務攔截器的長堆棧跟蹤,這意味着事務處理方面的工作。

+0

當然,我可能是錯的,但我不相信這是準確的。我可以完全刪除Transactional標籤,並仍然從數據庫中查詢和檢索數據。我的理解是@Transactional隻影響到數據庫的持久數據。此外,沒有錯誤。我可以遍歷代碼並將其放入Try/Catch塊,並且不會拋出任何可以看到的異常。 – cardician

+0

你沒有提到你用於持久化的技術。它是純JDBC嗎?在這種情況下,您可能不需要'@ Transactional',因爲每個語句都可以在自己的事務中運行(取決於配置)。這同樣適用於讀寫。查看'@ Transactional'是否應用了方法內部的打印堆棧跟蹤。如果你看到很多事務攔截器的長堆棧跟蹤,這意味着事務處理方面的工作。我幾乎無法想象數據不會沒有任何錯誤地持續存在。 –

+0

對不起,我並不感到驚訝,我忘了一些東西。我通過Hibernate使用JPA連接到MySQL數據庫。我在上面添加了我的配置文件。另外,如果沒有任何東西被拋出,我怎麼能從stacktrace打印任何東西?我會玩弄它,看看我猜。 – cardician

0

試試這個

  • 添加背景部件掃描到春天,法院data.xml中

    <context:component-scan base-package="com.springcourt" /> 
    
  • 測試服務隔離,創建一個JUnit測試一些這樣的事

    @RunWith(SpringJUnit4ClassRunner.class) 
    @ContextConfiguration(locations={"classpath:springcourt-data.xml"}) 
    @Transactional 
    public class ReservationServiceImplTest() 
    { 
        @Autowired 
        ReservationServiceImpl service; 
    
        @Test 
         public void validateContext() 
         { 
          Assert.assertNotNull(service); 
         } 
    
         @Test 
         @Rollback(false) 
         public void save() 
         { 
         service.save(data); 
         } 
    
    } 
    
+0

感謝您的回答。這似乎並不奏效,但結合gkamal的回答,似乎解決了這個問題。我明顯不理解配置文件的層次結構,因爲我已經完成了這些配置文件的分解,而且我沒有讀過任何書籍。 – cardician

1

我有同樣的問題,並解決它。組件掃描至網絡和數據層面,像這樣:

首先你必須分開的背景下

<!--in springcourt-servlet.xml --> 
<context:component-scan base-package="com.springcourt.web" /> 

<!--in springcourt-data.xml --> 
<context:component-scan base-package="com.springcourt.dao" /> 

2日加入springcourt-data.xml中

<aop:aspectj-autoproxy/> 

我希望這將是有幫助

0

一個非常好的選擇,你有什麼是使用以下內容:'

@Configuration 
@EnableAspectJAutoProxy(proxyTargetClass=true) 
public class AppConfig { 
    (...) 
} 

你需要做的是注入一切在相同的範圍內。如前所述,一種方法是更改​​ApplicationContext xml,另一種方法是像Spring代理一樣使用CGLIB,以便獲得基於子類的代理,並在那裏編寫您的bean實現和定義。

延伸閱讀:

相關問題