2012-09-07 10 views
10

मुझे अपनी समस्या का हल ढूंढने में कठिनाई हो रही है।
मेरे पास एक सेवा वर्ग है, जिसमें लॉगिन पर सत्यापन ध्वज सेट करने का एक तरीका है।TransactionRequiredException: अद्यतन/हटाए गए क्वेरी को निष्पादित करना

@Service("userRolesService") 
@Repository 
@Transactional 
public class UserRolesService { 
    public void verify() { 
     repository.verifyUser(); 
    } 
} 

मेरे भंडार एक SpringData CrudRepository है, और verifyUser तरह

@Modifying 
@Query("UPDATE user SET (verified = 1 WHERE verified=0)") 
public void verifyUser(); 

जब सीधे कोड बुला एक इकाई परीक्षण में, सब कुछ ठीक काम करता है कुछ है।

javax.persistence.TransactionRequiredException:: जब आवेदन के माध्यम से अपने प्रमाणीकरण प्रदाता से यह बुला रहा निम्नलिखित अपवाद एक अद्यतन निष्पादित/हटाने क्वेरी

सेवा वर्ग दोनों मेरे यूनिट टेस्ट और प्रमाणीकरण प्रदाता में इंजेक्ट किया जाता @Autowired एनोटेशन का उपयोग कर। परीक्षण में स्वयं कोई दिलचस्प टिप्पणी नहीं होती है, न ही प्रमाणीकरण प्रदाता करता है।

मैं विचारों से ताजा हूं, इसलिए यदि किसी के पास कोई सुराग है, तो मैं बहुत आभारी हूं।

संपादित करें: सत्यापन उपयोगकर्ता अद्यतन स्क्रिप्ट को कॉल करने के बजाय अब मैं सभी असत्यापित उपयोगकर्ताओं को पुनर्प्राप्त करता हूं, सत्यापित ध्वज सेट करता हूं और भंडार की बचत() विधि का उपयोग करता हूं। यह काम करता है, लेकिन बहुत बदसूरत है, इसलिए मैं बेहतर सुझावों के लिए खुला हूं।

EDIT2:

अनुरोध यहां प्रति config के हठ हिस्सा है, मुझे लगता है कि यह सबसे अधिक प्रासंगिक है, बाकी केवल प्रमाणीकरण से संबंधित है। इस कॉन्फ़िगरेशन का उपयोग यूनिट परीक्षण और वेब ऐप दोनों में किया जाता है, केवल अंतर यह है कि डेटा स्रोतों को यूनिट परीक्षणों और वेब ऐप के लिए MySQL के लिए एच 2 डीबी एम्बेडेड किया जाता है।

<beans [..]> 

    <bean id="entityManagerFactory" 
      class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" 
      depends-on="persistenceInitializer"> 
     <property name="dataSource" ref="dataSource"/> 
     <property name="persistenceUnitName" value="jpa"/> 
     <property name="packagesToScan"> 
      <list> 
       <value>com.example.model</value> 
      </list> 
     </property> 
     <property name="jpaVendorAdapter"> 
      <bean class="com.example.persistence.adapter.ConfigurationRetainingHibernateJpaVendorAdapter"> 
       <property name="database" value="${spring.hibernate.database}"/> 
       <property name="generateDdl" value="${spring.hibernate.generateDdl}"/> 
      </bean> 
     </property> 
     <property name="jpaProperties"> 
      <props> 
       <prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.DefaultComponentSafeNamingStrategy 
       </prop> 
      </props> 
     </property> 
    </bean> 

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

    <jpa:repositories base-package="com.example.persistence.repository"/> 

    <tx:annotation-driven/> 

    <bean id="persistenceInitializer" class="com.example.persistence.init.NoOpInitializer"/> 

</beans> 

साथ ही मैं एक config है कि केवल वेब एप्लिकेशन में, नहीं इकाई परीक्षण है:

<beans [..]> 

    <bean id="propertyConfigurer" 
      class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> 
     <property name="locations"> 
      <list> 
       <value>classpath:application.properties</value> 
      </list> 
     </property> 
    </bean> 

    <mvc:annotation-driven/> 

    <mvc:default-servlet-handler/> 

    <context:annotation-config/> 

</beans> 
+0

आपके द्वारा पोस्ट की हैं अपने स्प्रिंग जोड़कर हल config? ऐसा लगता है कि आपके लेनदेन पोस्ट प्रोसेसर को बीन नहीं मिल रहा है? – MarkOfHall

+0

निश्चित बात, दो कॉन्फ़िगरेशन भागों को जोड़ा गया। कॉन्फ़िगर कई फ़ाइलों में विभाजित है, उनमें से अधिकतर इस समस्या के लिए प्रासंगिक नहीं होना चाहिए। – pushy

उत्तर

8

मुझे लगता है कि अगर आप <context:annotation-config/> युक्त संदर्भ में <tx:annotation-driven/> ले जाते हैं, तो वसंत लेने जाएगा आपका @Transactional<tx:annotation-driven/> एक पोस्ट प्रोसेसर है जो केवल उस संदर्भ में बीन्स को सजाने के लिए प्रस्तुत करता है, जिसमें इसे परिभाषित किया गया है। आगे के स्पष्टीकरण के लिए मेरा उत्तर here देखें।

+0

यह काम करता है, ऐसा लगता है कि यह मेरी गलती थी। अंत में मैंने दोनों उत्तरों का उपयोग किया, लेकिन ऐसा लगता है कि कोड काम कर रहा है, बहुत धन्यवाद :-) – pushy

4

- यहाँ अपने applicationContext.xml देखना चाहिए कि कैसे है - आपकी सेवा वर्ग भी भंडार

नहीं होना चाहिए:

<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager"> 
    <property name="entityManagerFactory" ref="entityManagerFactory"/> 
</bean> 
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/> 
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory"> 
    <property name="persistenceUnitName" value="persistenceUnit"/> 
    <property name="dataSource" ref="dataSource"/> 
</bean> 

<bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" id="dataSource"> 
    <property name="driverClassName" value="${database.driverClassName}"/> 
    <property name="url" value="${database.url}"/> 
    <property name="username" value="${database.username}"/> 
    <property name="password" value="${database.password}"/> 
    <property name="testOnBorrow" value="true"/> 
    <property name="testOnReturn" value="true"/> 
    <property name="testWhileIdle" value="true"/> 
    <property name="timeBetweenEvictionRunsMillis" value="1800000"/> 
    <property name="numTestsPerEvictionRun" value="3"/> 
    <property name="minEvictableIdleTimeMillis" value="1800000"/> 
    <property name="validationQuery" value="SELECT 1"/> 
    <property name="initialSize" value="1"/> 
    <property name="minIdle" value="1"/> 
    <property name="maxActive" value="10"/> 
    <property name="poolPreparedStatements" value="true"/> 
    <property name="maxOpenPreparedStatements" value="20"/> 
</bean> 

- यहां अपने इकाई परीक्षण कक्षाओं चाहिए है परिभाषित किया जा सकता है

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(loader=WebContextLoader.class, locations = {"classpath:/META-INF/spring/applicationContext.xml", "classpath:/META-INF/spring/applicationContext-test-override.xml"}) 
public class MyTest { 

- एप्लिकेशन कॉन्टेक्स्ट-टेस्ट-ओवरराइड.एक्सएमएल का उपयोग ध्यान दें यह परीक्षण के लिए आपके संदर्भ में किसी भी सेटिंग को ओवरराइड करने के लिए उपयोग किया जाता है।ऐसा करने से इसका मतलब है कि आप असली एप्लिकेशन संदर्भ का परीक्षण कर रहे हैं, इसलिए यदि आप वहां गलतियां करते हैं, तो यह आपके परीक्षणों में आ जाएगा। यह src/test/संसाधनों में स्थित होना चाहिए। यह सब आप उम्मीद है कि जरूरत है:

<bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" id="dataSource"> 
    <property name="url" value="${database-test.url}"/> 
</bean> 

- (वैकल्पिक) मोड का उपयोग करने = AspectJ

Maven प्लगइन्स के लिए निम्न जोड़ें। यह रनटाइम (मोड = प्रॉक्सी) की बजाय संकलन समय पर पहलुओं को शामिल करता है।

 <plugin> 
      <groupId>org.codehaus.mojo</groupId> 
      <artifactId>aspectj-maven-plugin</artifactId> 
      <version>1.4</version> 
      <dependencies> 
       <dependency> 
        <groupId>org.aspectj</groupId> 
        <artifactId>aspectjrt</artifactId> 
        <version>${aspectj.version}</version> 
       </dependency> 
       <dependency> 
        <groupId>org.aspectj</groupId> 
        <artifactId>aspectjtools</artifactId> 
        <version>${aspectj.version}</version> 
       </dependency> 
      </dependencies> 
      <executions> 
       <execution> 
        <goals> 
         <goal>compile</goal> 
         <goal>test-compile</goal> 
        </goals> 
        <!-- NB: force aspect compile before normal compile, required for 1.3+ 
         see: MASPECTJ-13, MASPECTJ-92 --> 
        <phase>process-sources</phase> 
       </execution> 
      </executions> 
      <configuration> 
       <outxml>true</outxml> 
       <aspectLibraries> 
        <aspectLibrary> 
         <groupId>org.springframework</groupId> 
         <artifactId>spring-aspects</artifactId> 
        </aspectLibrary> 
       </aspectLibraries> 
       <source>${java.version}</source> 
       <target>${java.version}</target> 
      </configuration> 
     </plugin> 
+0

जैसे ही मैं मोड = "aspectj" लेनदेन-प्रबंधक = "लेनदेन प्रबंधक" को अपने टीएक्स में जोड़ता हूं: एनोटेशन -डिवन टैग, मुझे अपने यूनिट परीक्षणों में त्रुटि भी मिलती है। इसके अलावा applcationContext.xml में परिवर्तन बहुत समझ में आता है, मैंने उनको पेश किया। फिर भी, अपवाद पॉप अप पर रहता है। – pushy

+0

उत्तर – Solubris

+0

पर मोड = पहलू का उपयोग करने पर अतिरिक्त बिंदु जोड़ा गया, अब यह काम कर रहा है, बहुत बहुत धन्यवाद। स्टीव का जवाब समाधान साबित हुआ, लेकिन मेरी कॉन्फ़िगरेशन फ़ाइलों को फिर से काम करना थोड़ी देर के लिए था, इसलिए इनपुट के लिए धन्यवाद। पहलू एनोटेशन मोड को काम करने के लिए नहीं मिला, लेकिन यह प्रॉक्सी मोड के साथ ठीक काम करता है। – pushy

1

मैं कुछ समस्या थी और मैं बस सेवा विधि को हटाने या अद्यतन प्रदर्शन उस पर @Transactional एनोटेशन जोड़कर संकल्प लिया।

0

मैं भी यही समस्या का सामना करना पड़ा और वे टिप्पणियां @Transactional (प्रचार = Propagation.REQUIRED, rollbackFor = Exception.class, केवल पढ़ने के लिए = false)

@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class, readOnly = false) 
public class UserRolesService{ 
.......... 
}