type transaction transacciones example java spring spring-mvc web-applications

java - transaction - transacciones jpa



Spring: no hay EntityManager con una transacción real disponible para el subproceso actual: no se puede procesar de manera confiable la llamada ''persistente'' (12)

Este error me hizo perder el tiempo durante tres días, la situación que enfrenté produjo el mismo error. Siguiendo todos los consejos que pude encontrar, jugué con la configuración pero fue en vano.

Finalmente lo encontré, la diferencia, el Servicio que estaba ejecutando estaba contenido en un frasco común, el problema resultó ser que AspectJ no trataba la instanciación del Servicio de la misma manera. En efecto, el proxy simplemente estaba llamando al método subyacente sin que se ejecutara toda la magia Spring normal antes de la llamada al método.

Al final, la anotación @Scope colocada en el servicio según el ejemplo resolvió el problema:

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

El método que he publicado es un método de eliminación, pero las anotaciones afectan a todos los métodos de persistencia de la misma manera.

Espero que esta publicación ayude a alguien que ha tenido problemas con el mismo problema al cargar un servicio desde un jar

Recibo este error cuando intento invocar el método "persistente" para guardar el modelo de entidad en la base de datos en mi aplicación web Spring MVC. Realmente no puedo encontrar ninguna publicación o página en Internet que pueda relacionarse con este error en particular. Parece que algo está mal con el bean EntityManagerFactory, pero soy bastante nuevo en la programación de Spring, así que para mí parece que todo está bien inicializado y de acuerdo con varios artículos de tutoriales en la web.

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


Esto nos ayudó, tal vez pueda ayudar a otros en el futuro. @Transaction no funcionaba para nosotros, pero esto sí:

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


Obtuve esta excepción al intentar usar un método personalizado deleteBy en el repositorio de datos de Spring. La operación se intentó desde una clase de prueba JUnit.

La excepción no ocurre al usar la anotación @Transactional en el nivel de clase JUnit.


Para nosotros, el problema se redujo a la misma configuración de contexto en múltiples archivos de configuración. Compruebe que no ha duplicado lo siguiente en varios archivos de configuración.

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


Quité el modo de

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

para hacer que esto funcione


Tuve el mismo código de error cuando utilicé @Transaction en un método / nivel de acción incorrecto.

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

Tuve que colocar el @Transactional justo encima del método methodWithANumberOfDatabaseActions() , por supuesto.

Eso resolvió el mensaje de error en mi caso.


Tuve el mismo error al acceder a un método anotado ya transaccionalmente desde un método no transaccional dentro del mismo componente:

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

Solucioné el error llamando a executeQuery () en el componente auto-referenciado:

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



Tuve el mismo problema y @Transactional el método como @Transactional y funcionó.

ACTUALIZACIÓN: comprobando la documentación de primavera, parece que, por defecto, el PersistenceContext es de tipo Transacción, por eso el método tiene que ser transaccional ( http://docs.spring.io/spring/docs/current/spring-framework-reference/html/orm.html ):

La anotación @PersistenceContext tiene un tipo de atributo opcional, que por defecto es PersistenceContextType.TRANSACTION. Este valor predeterminado es lo que necesita para recibir un proxy EntityManager compartido. La alternativa, PersistenceContextType.EXTENDED, es un asunto completamente diferente: esto da como resultado un EntityManager extendido, que no es seguro para subprocesos y, por lo tanto, no debe usarse en un componente al que se accede simultáneamente, como un bean singleton administrado por Spring. Se supone que los EntityManagers extendidos solo se usan en componentes con estado que, por ejemplo, residen en una sesión, con el ciclo de vida del EntityManager no vinculado a una transacción actual, sino que depende completamente de la aplicación.


Tuve el mismo problema y agregué tx:annotation-driven en tx:annotation-driven en applicationContext.xml y funcionó.


Tuve este problema durante días y nada de lo que encontré en línea me ayudó, estoy publicando mi respuesta aquí en caso de que ayude a alguien más.

En mi caso, estaba trabajando en un microservicio que se llamaba a través de la comunicación remota, y el proxy remoto no estaba recogiendo mi anotación @Transactional a nivel de servicio.

Agregar una clase de delegado entre las capas de servicio y dao y marcar el método de delegado como transaccional me arregló esto.


boardRepo.deleteByBoardId (id);

Enfrenté el mismo problema. GOT javax.persistence.TransactionRequiredException: no hay EntityManager con transacción real disponible para el hilo actual

Lo resolví agregando la anotación @Transactional sobre el controlador / servicio.