स्प्रिंग - वर्तमान थ्रेड के लिए उपलब्ध वास्तविक लेनदेन के साथ कोई एंटिटी मैनजर - ​​मज़बूती से 'लगातार' कॉल को संसाधित नहीं कर सकता है


137

मुझे यह त्रुटि तब आती है जब मैं अपने स्प्रिंग एमवीसी वेब एप्लिकेशन में डेटाबेस के लिए इकाई मॉडल को बचाने के लिए "जारी" रखने की कोशिश करता हूं। वास्तव में इंटरनेट में कोई पोस्ट या पेज नहीं मिल सकता है जो इस विशेष त्रुटि से संबंधित हो। यह EntityManagerFactory सेम के साथ कुछ गलत लगता है, लेकिन मैं वसंत प्रोग्रामिंग के लिए काफी नया हूं, इसलिए मेरे लिए ऐसा लगता है कि सब कुछ प्रारंभिक रूप से ठीक है और वेब में विभिन्न ट्यूटोरियल लेखों के अनुसार।

डिस्पैचर-servlet.xml

<?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:mvc="http://www.springframework.org/schema/mvc"
 xmlns:context="http://www.springframework.org/schema/context"
 xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="
 http://www.springframework.org/schema/mvc 
 http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
 http://www.springframework.org/schema/beans 
 http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
 http://www.springframework.org/schema/context 
  http://www.springframework.org/schema/context/spring-context-4.0.xsd
  http://www.springframework.org/schema/jdbc
  http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
  http://www.springframework.org/schema/data/jpa
  http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
  http://www.springframework.org/schema/data/repository
  http://www.springframework.org/schema/data/repository/spring-repository-1.5.xsd
  http://www.springframework.org/schema/jee
  http://www.springframework.org/schema/jee/spring-jee-3.2.xsd">

    <context:component-scan base-package="wymysl.Controllers" />
    <jpa:repositories base-package="wymysl.repositories"/> 
    <context:component-scan base-package="wymysl.beans" /> 
    <context:component-scan base-package="wymysl.Validators" /> 
    <bean
     class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
     <bean class="org.springframework.orm.hibernate4.HibernateExceptionTranslator"/>

     <bean id="passwordValidator" class="wymysl.Validators.PasswordValidator"></bean>

     <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">

        <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
        <property name="url" value="jdbc:oracle:thin:@localhost:1521:xe" />
        <property name="username" value="system" />
        <property name="password" value="polskabieda1" />
    </bean>

 <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceXmlLocation" value="classpath:./META-INF/persistence.xml" />
    <property name="dataSource" ref="dataSource" />

    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="databasePlatform" value="org.hibernate.dialect.H2Dialect" />
            <property name="showSql" value="true" />
            <property name="generateDdl" value="false" />
        </bean>
    </property>
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.max_fetch_depth">3</prop>
            <prop key="hibernate.jdbc.fetch_size">50</prop>
            <prop key="hibernate.jdbc.batch_size">10</prop>
        </props>
    </property>
</bean>

    <mvc:annotation-driven />

    <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <property name="basename" value="classpath:messages" />
</bean>

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


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

    <mvc:resources mapping="/resources/**" location="/resources/" />
    <mvc:resources mapping="/resources/*" location="/resources/css/"  
    cache-period="31556926"/>



</beans>

RegisterController.java

@Controller
public class RegisterController {

    @PersistenceContext
    EntityManager entityManager;

    @Autowired
    PasswordValidator passwordValidator;

    @InitBinder
    private void initBinder(WebDataBinder binder) {
        binder.setValidator(passwordValidator);
    }

    @RequestMapping(value = "/addUser", method = RequestMethod.GET)
    public String register(Person person) {


        return "register";

    }

    @RequestMapping(value = "/addUser", method = RequestMethod.POST)
    public String register(@ModelAttribute("person") @Valid @Validated Person person, BindingResult result) {
        if(result.hasErrors()) {
            return "register";
        } else {
            entityManager.persist(person);
            return "index";

        }




    }

1
जैसा कि त्रुटि कहती है, कोई लेनदेन नहीं है। के साथ रजिस्टर विधि का उल्लेख करें @Transaction
रोहित

जवाबों:


260

मुझे भी यही समस्या थी और मैंने इस पद्धति को एनोटेट किया @Transactionalऔर इसने काम किया।

अद्यतन: डिफ़ॉल्ट रूप से ऐसा प्रतीत होता है कि वसंत के दस्तावेज़ की जांच पर्सिस्टेंस कॉन्टेक्स्ट प्रकार के लेन-देन की है, इसीलिए इस पद्धति का लेन-देन करना होगा ( http://docs.spring.io/spring/docs/burrent/spring-framework-reference/ html / orm.html ):

@PersistenceContext एनोटेशन में एक वैकल्पिक विशेषता प्रकार होता है, जो PersistenceContextType.TRANSACTION के लिए डिफ़ॉल्ट होता है। यह डिफ़ॉल्ट है जिसे आपको एक साझा EntityManager प्रॉक्सी प्राप्त करने की आवश्यकता है। वैकल्पिक, PersistenceContextType.EXTENDED, एक पूरी तरह से अलग मामला है: यह एक तथाकथित विस्तारित EntityManager में परिणाम करता है, जो थ्रेड-सुरक्षित नहीं है और इसलिए इसे स्प्रिंग-प्रबंधित सिंगलटन बीन के रूप में समवर्ती एक्सेस वाले घटक में उपयोग नहीं किया जाना चाहिए। विस्तारित एंटिटी मैनेजर का उपयोग केवल स्टेटफुल घटकों में किया जाना चाहिए, उदाहरण के लिए, एक सत्र में निवास करते हैं, एंटिटीमैन के जीवनचक्र को एक वर्तमान लेनदेन से जोड़ा नहीं जाता है, बल्कि पूरी तरह से एप्लिकेशन तक होता है।


71
यदि @Transactionalएनाउंसमेंट के बिना एक विधि उसी क्लासफाइल में @Transactionalएनोटेशन के साथ एक विधि कहती है , तो आप भी इस त्रुटि से प्रभावित होंगे (यही वह है जो मैं सामना कर रहा था)।
जैकब वैन लिंगन

5
मैंने सेवा वर्ग के साथ एनोटेट किया @Transactional, वह भी काम करता है। यकीन नहीं होता अगर यह जाने का सही तरीका है, लेकिन ऐसा लगता है कि यह ठीक काम कर रहा है ...
milosmns

8
एक और बात ध्यान देने योग्य है कि इस एनोटेशन का उपयोग सार्वजनिक विधि के लिए किया जाना चाहिए क्योंकि यह अन्यथा काम नहीं करता है।
युरी क्रावट्स

7
याद रखें, कृपया, कि @ ट्रेंसेक्शनल केवल सार्वजनिक तरीकों पर काम करता है।
आंद्रेई _N_N 31:17

7
FYI करें इसके लिए javax.transaction.Transactional एनोटेशन (स्प्रिंग एक नहीं) की आवश्यकता है।
जावा-आदी ३०१

85

स्प्रिंग डेटा रिपॉजिटरी में एक हटाने योग्य कस्टम विधि का उपयोग करने का प्रयास करते हुए मुझे यह अपवाद मिला। ऑपरेशन का प्रयास एक जेयूनिट टेस्ट क्लास से किया गया था।

@TransactionalJUnit वर्ग स्तर पर एनोटेशन का उपयोग करने पर अपवाद नहीं होता है।


8
मैं उसी स्थिति में था, मैंने टेस्ट-क्लास को एनोटेट करने के बजाय सेवा पद्धति को एनोटेट किया था, इसलिए यह परीक्षण नहीं होने पर भी नीचे गिर गया।
पॉल नेल्सन बेकर

@Transactionalएक वर्ग-स्तर पर संभव परीक्षण समस्याओं का सामना कर सकते हैं जो आपकी सेवाओं में विभिन्न लेनदेन में हेरफेर करते हैं।
ज़ोन

1
मैंने @Trasactionalरिपॉजिटरी पद्धति का उपयोग उस जगह से किया, जहां मैं वास्तव में डेटाबेस और इसके ठीक काम करने के साथ बातचीत कर रहा हूं।
हरीश कुमार सैनी

22

इस त्रुटि ने मुझे तीन दिनों के लिए लोमड़ी बना दिया था, जिस स्थिति का मैंने सामना किया, उसी त्रुटि का उत्पादन किया। मुझे मिल रही सभी सलाह के बाद, मैंने कॉन्फ़िगरेशन के साथ खेला लेकिन कोई फायदा नहीं हुआ।

आखिरकार मुझे यह पता चला, अंतर, मैं जिस सेवा को निष्पादित कर रहा था, वह एक सामान्य जार में समाहित थी, यह मुद्दा एस्पेक्टज के समान था, जो सेवा की तात्कालिकता का इलाज नहीं कर रहा था। वास्तव में छद्म तरीके से सभी सामान्य स्प्रिंग जादू के बिना अंतर्निहित विधि को कॉल किया जा रहा था।

अंत में उदाहरण के अनुसार सेवा पर रखा गया @ स्कोप एनोटेशन समस्या को हल करता है:

@Service
@Scope(proxyMode = ScopedProxyMode.INTERFACES)
@Transactional
public class CoreServiceImpl implements CoreService {
    @PersistenceContext
    protected EntityManager entityManager;

    @Override
    public final <T extends AbstractEntity> int deleteAll(Class<T> clazz) {
        CriteriaDelete<T> criteriaDelete = entityManager.getCriteriaBuilder().createCriteriaDelete(clazz);
        criteriaDelete.from(clazz);
        return entityManager.createQuery(criteriaDelete).executeUpdate();
    }

}

मेरे द्वारा पोस्ट की गई विधि एक डिलीट विधि है, लेकिन एनोटेशन उसी तरह से सभी दृढ़ता तरीकों को प्रभावित करते हैं।

मुझे उम्मीद है कि यह पोस्ट किसी और की मदद करती है जो एक जार से सेवा लोड करते समय उसी मुद्दे से जूझता है


@Scope(proxyMode = ScopedProxyMode.INTERFACES)DAO वर्ग को जोड़ना जो एक इंटरफ़ेस को लागू करता है वास्तव में महत्वपूर्ण है। मैंने इस त्रुटि का पता लगाने के लिए पूरा दिन बिताया और आपका समाधान केवल एक ही काम है। आपका बहुत बहुत धन्यवाद!
थाच वान

1
आपके उत्तर से एक लोटनोटेशन ने शायद मुझे लगभग 3 दिन बचा लिया है। मैंने अभी एडेनमा की वास्तविक शक्ति का अनुभव किया है। Дякс।
ओलेक्सी किस्लीत्सिन

11

मेरे पास एक ही त्रुटि थी क्योंकि मैंने XML- से जावा-कॉन्फ़िगरेशन पर स्विच किया था।

बिंदु यह था, मैं <tx:annotation-driven/>टैग नहीं माइग्रेट करता था , जैसा कि स्टोन फेंग ने सुझाव दिया था।

इसलिए मैंने अभी @EnableTransactionManagementसुझाव दिया है कि यहाँ @Configuration Class में स्प्रिंग में एनोटेशन ड्रिवेन ट्रांजैक्शंस सेट करना है , और यह अब काम करता है


8

boardRepo.deleteByBoardId (आईडी);

उसी मुद्दे का सामना किया। GOT javax.persistence.TransactionRequiredException: वर्तमान थ्रेड के लिए उपलब्ध वास्तविक लेनदेन वाला कोई EntityManager नहीं

मैंने कंट्रोलर / सर्विस के ऊपर @ ट्रान्सऐक्टिव एनोटेशन जोड़कर इसे हल किया ।


7

मैं एक ही समस्या थी और मैं जोड़ा tx:annotation-drivenमें applicationContext.xmlहै और यह काम किया।


4

एक ही घटक के भीतर एक गैर-लेन-देन विधि से पहले से ही लेनदेन-एनोटेट विधि तक पहुँचने पर मुझे एक ही त्रुटि हुई थी:

Before:
    @Component
    public class MarketObserver {
        @PersistenceContext(unitName = "maindb")
        private EntityManager em;

        @Transactional(value = "txMain", propagation = Propagation.REQUIRES_NEW)
        public void executeQuery() {
          em.persist(....);
        }


        @Async
        public void startObserving() {
          executeQuery(); //<-- Wrong
        }
    }

    //In another bean:
     marketObserver.startObserving();

मैंने स्वयं-संदर्भित घटक पर executeQuery () कॉल करके त्रुटि को ठीक किया:

Fixed version:
    @Component
    public class MarketObserver {
        @PersistenceContext(unitName = "maindb")
        private EntityManager em;

        @Autowired
        private GenericApplicationContext context;

        @Transactional(value = "txMain", propagation = Propagation.REQUIRES_NEW)
        public void executeQuery() {
          em.persist(....);
        }


        @Async
        public void startObserving() {
          context.getBean(MarketObserver.class).executeQuery(); //<-- Works
        }
    }

3

org.springframework.transaction.annotation.Transactionalपरीक्षण वर्ग के लिए वर्ग स्तर पर एनोटेशन जोड़ना मेरे लिए मुद्दा तय किया।


3

अन्य उपयोगकर्ताओं के लिए बस एक नोट जो थिए एरर के लिए उत्तर खोज रहा है। एक और आम मुद्दा है:

आप आम तौर पर एक @transactionalही वर्ग के भीतर से एक विधि नहीं कह सकते ।

(AspectJ का उपयोग करने के तरीके और साधन हैं, लेकिन रिफैक्टिंग करना आसान होगा)

तो आपको कॉलिंग क्लास और क्लास की आवश्यकता होगी जो रखती है @transactional विधियों को ।


2

हमारे लिए, समस्या एकाधिक कॉन्फ़िगरेशन फ़ाइलों में समान संदर्भ सेटिंग्स पर आ गई। जाँचें कि आपने एकाधिक कॉन्फ़िग फ़ाइलों में निम्नलिखित को दोहराया नहीं है।

<context:property-placeholder location="classpath*:/module.properties"/>
<context:component-scan base-package="...." />

2

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

methodWithANumberOfDatabaseActions() { 
   methodA( ...)
   methodA( ...)
}

@Transactional
void methodA( ...) {
  ... ERROR message
}

मुझे @Transactionalविधि के ठीक ऊपर रखना थाmethodWithANumberOfDatabaseActions() , बिल्कुल।

इससे मेरे मामले में त्रुटि संदेश हल हो गया।


0

मैंने उस मोड को हटा दिया

<tx:annotation-driven mode="aspectj"
transaction-manager="transactionManager" />

यह काम करने के लिए


0

मेरे पास यह मुद्दा था दिनों के लिए और कुछ भी नहीं जो मैंने कहीं भी पाया ऑनलाइन मेरी मदद की, मैं अपना जवाब यहां पोस्ट कर रहा हूं अगर यह किसी और की मदद करता है।

मेरे मामले में, मैं एक microservice पर काम कर रहा था जिसे रिमोटिंग के माध्यम से बुलाया जा रहा था, और सेवा स्तर पर मेरे @ ट्रान्सटेक्शनल एनोटेशन को दूरस्थ प्रॉक्सी द्वारा नहीं उठाया जा रहा था।

सेवा और डाओ परतों के बीच एक प्रतिनिधि वर्ग जोड़ना और प्रतिनिधि विधि को चिह्नित करना, जैसा कि मेरे लिए लेन-देन तय है।


0

इससे हमें मदद मिली, शायद यह भविष्य में दूसरों की मदद कर सके। @Transactionहमारे लिए काम नहीं कर रहा था, लेकिन यह किया:

@ConditionalOnMissingClass("org.springframework.orm.jpa.JpaTransactionManager")


0

यदि आपके पास है

@Transactional // Spring Transactional
class MyDao extends Dao {
}

और सुपर-क्लास

class Dao {
    public void save(Entity entity) { getEntityManager().merge(entity); }
}

और तुम बुलाओ

@Autowired MyDao myDao;
myDao.save(entity);

आपको स्प्रिंग ट्रांज़ैक्शन इन्टरसेप्टर नहीं मिलेगा (जो आपको लेन-देन देता है)।

यह वह है जो आपको करना जरूरी है:

@Transactional 
class MyDao extends Dao {
    public void save(Entity entity) { super.save(entity); }
}

बात अविश्वसनीय जरूर है, लेकिन सही है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.