it-swarm.com.de

Spring - Für den aktuellen Thread ist kein EntityManager mit einer tatsächlichen Transaktion verfügbar - kann einen "dauerhaften" Anruf nicht zuverlässig verarbeiten

Ich erhalte diesen Fehler, wenn ich versuche, die Methode "persist" aufzurufen, um das Entitätsmodell in meiner Spring MVC-Webanwendung in der Datenbank zu speichern. Ich kann im Internet keine Posts oder Seiten finden, die sich auf diesen bestimmten Fehler beziehen können. Es sieht so aus, als ob etwas mit EntityManagerFactory-Bean nicht in Ordnung ist, aber ich bin ziemlich neu in der Frühlingsprogrammierung. Für mich sieht es also so aus, als ob alles in Ordnung und gemäß verschiedenen Tutorial-Artikeln im Web initialisiert ist.

dispatcher-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";

        }




    }
96
Michał Bil

Ich hatte das gleiche Problem und habe die Methode wie folgt kommentiert: @Transactional und es hat funktioniert.

AKTUALISIERUNG: In der Frühlingsdokumentation sieht es so aus, als ob der PersistenceContext standardmäßig vom Typ Transaction ist. Deshalb muss die Methode transactional sein ( http://docs.spring.io/spring/docs/current/spring- Framework-Referenz/html/orm.html ):

Die Annotation @PersistenceContext verfügt über einen optionalen Attributtyp, der standardmäßig PersistenceContextType.TRANSACTION lautet. Diese Standardeinstellung ist erforderlich, um einen freigegebenen EntityManager-Proxy zu erhalten. Die Alternative PersistenceContextType.EXTENDED ist eine völlig andere Angelegenheit: Dies führt zu einem sogenannten erweiterten EntityManager, der nicht threadsicher ist und daher nicht in einer Komponente verwendet werden darf, auf die gleichzeitig zugegriffen wird, z. B. in einer Spring-verwalteten Singleton-Bean. Extended EntityManager sollten nur in statusbehafteten Komponenten verwendet werden, die sich beispielsweise in einer Sitzung befinden, wobei der Lebenszyklus des EntityManagers nicht an eine aktuelle Transaktion gebunden ist, sondern vollständig der Anwendung entspricht.

195
mlg

Diese Ausnahme trat auf, als ich versuchte, eine benutzerdefinierte Methode deleteBy im Frühjahrsdatenrepository zu verwenden. Die Operation wurde in einer JUnit-Testklasse versucht.

Die Ausnahme tritt nicht auf, wenn die Annotation @Transactional Auf der JUnit-Klassenebene verwendet wird.

60

Dieser Fehler ließ mich drei Tage lang fuchsieren, die Situation, mit der ich konfrontiert war, erzeugte denselben Fehler. Nach all den Ratschlägen, die ich finden konnte, spielte ich mit der Konfiguration, aber ohne Erfolg.

Schließlich fand ich heraus, dass der Unterschied, den ich ausführte, in einem gemeinsamen Jar enthalten war. Es stellte sich heraus, dass AspectJ die Service-Instanziierung nicht gleich behandelte. Tatsächlich hat der Proxy einfach die zugrunde liegende Methode aufgerufen, ohne dass die gesamte normale Spring-Magie vor dem Methodenaufruf ausgeführt wurde.

Am Ende löste die @Scope-Annotation, die gemäß dem Beispiel für den Service platziert wurde, das Problem:

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

}

Die von mir veröffentlichte Methode ist eine Löschmethode, die Anmerkungen wirken sich jedoch auf alle Persistenzmethoden auf dieselbe Weise aus.

Ich hoffe, dieser Beitrag hilft jemandem, der mit dem gleichen Problem zu kämpfen hat, wenn er einen Service aus einem Glas lädt

15
Chris March

Ich hatte den gleichen Fehler, weil ich von der XML- zur Java-Konfiguration gewechselt bin.

Der Punkt war, ich habe nicht migriert <tx:annotation-driven/> Tag, wie Stone Feng vorschlug.

Also habe ich gerade @EnableTransactionManagement wie hier vorgeschlagen Einrichten von mit Anmerkungen versehenen Transaktionen im Frühjahr in der @ Configuration-Klasse , und es funktioniert jetzt

7
Sergej Werfel

Ich hatte das gleiche Problem und fügte hinzu, tx:annotation-driven im applicationContext.xml und es hat funktioniert.

4
Stone Feng

boardRepo.deleteByBoardId (id);

Konfrontiert das gleiche Problem. GOT javax.persistence.TransactionRequiredException: Kein EntityManager mit tatsächlicher Transaktion für den aktuellen Thread verfügbar

Ich habe es gelöst, indem ich @ Transactional Anmerkung über dem Controller/Dienst hinzufügte.

2
Vikram S

Ich hatte den gleichen Fehler beim Zugriff auf eine bereits mit Transaktionsanmerkungen versehene Methode von einer nicht-transaktionsbezogenen Methode innerhalb derselben Komponente:

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();

Ich habe den Fehler behoben, indem ich die executeQuery () für die selbstreferenzierte Komponente aufgerufen habe:

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
        }
    }
1
YDZOGODOQ

Für uns lag das Problem an den gleichen Kontexteinstellungen in mehreren Konfigurationsdateien. Stellen Sie sicher, dass Sie Folgendes nicht in mehreren Konfigurationsdateien dupliziert haben.

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

Ich hatte den gleichen Fehlercode, als ich @Transaction Für eine falsche Methode/Aktionsebene verwendete.

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

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

Ich musste natürlich den @Transactional Direkt über der Methode methodWithANumberOfDatabaseActions() platzieren.

Das löste die Fehlermeldung in meinem Fall.

0
user9835597

Ich hatte dieses Problem seit Tagen und nichts, was ich online gefunden habe, hat mir geholfen. Ich poste meine Antwort hier, falls es jemand anderem hilft.

In meinem Fall arbeitete ich an einem Microservice, der durch Remoting aufgerufen wurde, und meine @ Transactional-Annotation auf Service-Ebene wurde vom Remote-Proxy nicht erfasst.

Das Hinzufügen einer Delegate-Klasse zwischen dem Service- und dem Dao-Layer und das Markieren der Delegate-Methode als Transaktions-Klasse haben dies für mich behoben.

0
fleeblewidget

Ich habe den Modus von entfernt

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

um diese Arbeit zu machen

0
ropo