Spring JavaFX @Transactional entitymanager 已关闭
Spring JavaFX @Transactional entitymanager is closed
我遇到了使用 Spring @Transactional 和 JavaFX 应用程序的事务问题,我所有的 bean 和图形组件都由 spring 管理。
我在我的控制器上使用@PostConstruct 初始化我的应用程序。
在 PostConstruct 中,我所有的 daos 都运行良好,但是当我通过按下 JavaFX 按钮调用服务来保存某些内容时,我得到了这个异常。
Caused by: org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is java.lang.IllegalStateException: EntityManagerFactory is closed
at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:431)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:463)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:276)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy48.saveGame(Unknown Source)
at dev.debizis.mtggui.desktop.controller.TemplateEditorController.handleSaveGameAction(TemplateEditorController.java:362)
... 68 more
Caused by: java.lang.IllegalStateException: EntityManagerFactory is closed
at org.hibernate.jpa.internal.EntityManagerFactoryImpl.validateNotClosed(EntityManagerFactoryImpl.java:388)
at org.hibernate.jpa.internal.EntityManagerFactoryImpl.internalCreateEntityManager(EntityManagerFactoryImpl.java:342)
at org.hibernate.jpa.internal.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:313)
at org.springframework.orm.jpa.JpaTransactionManager.createEntityManagerForTransaction(JpaTransactionManager.java:449)
at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:369)
... 76 more
有谁知道为什么 entityManager 不在方法上使用 @Transactonal 打开事务?
我的休眠 bean 配置:
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc.xsd">
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<!-- the property configurer for the datasource -->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>jdbc.properties</value>
</list>
</property>
<property name="ignoreUnresolvablePlaceholders" value="true" />
</bean>
<!-- the DataSource (parameterized for configuration via a PropertyPlaceHolderConfigurer) -->
<bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp2.BasicDataSource">
<property name="driverClassName" value="${h2.jdbc.driverClassName}" />
<property name="url" value="${h2.jdbc.url}" />
<property name="username" value="${h2.jdbc.username}" />
<property name="password" value="${h2.jdbc.password}" />
</bean>
<!-- Hibernate SessionFactory Definition Debug -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.cardassiel.dao.entity" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.connection.autocommit">false</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.H2Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">validate</prop>
<prop key="hibernate.bytecode.use_reflection_optimizer">true</prop>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider</prop>
<!-- <prop key="hibernate.enable_lazy_load_no_trans">true</prop> -->
</props>
</property>
</bean>
<!-- Hibernate Transaction Manager Definition -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
我的服务环境
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<import resource="classpath*:dao-context.xml" />
<import resource="classpath*:common-context.xml" />
<context:component-scan base-package="com.cardassiel.core.service" />
<context:component-scan base-package="com.cardassiel.core.mapper" />
<!-- hibernate transaction by annotations -->
<tx:annotation-driven transaction-manager="transactionManager" />
我的保存方式:
/** {@inheritDoc} */
@Override
@Transactional
public final Long saveGame(final GameDTO game) {
LOGGER.debug("saveGame : name = {}", game.getName());
return gameDao.saveOrUpdate(mapper.map(game, Game.class));
}
我的道法:
/** {@inheritDoc}*/
@SuppressWarnings("unchecked")
@Override
public final P saveOrUpdate(final T o) {
if (entityManager.getEntityManagerFactory().getPersistenceUnitUtil().getIdentifier(o) == null) {
entityManager.persist(o);
} else {
entityManager.merge(o);
}
return (P) entityManager.getEntityManagerFactory().getPersistenceUnitUtil().getIdentifier(o);
}
提前致谢。
通过阅读日志,我明白了发生了什么。
一个线程正在关闭 applicationContext,并隐含地关闭所有单例 bean,包括 entityManagerFactory!
entityManagerFactory 在每个 PersistenceUnit 生命周期中只能打开一次。
当 Transaction 尝试打开带有关闭工厂的 entityManager 时,它会抛出异常。
我遇到了使用 Spring @Transactional 和 JavaFX 应用程序的事务问题,我所有的 bean 和图形组件都由 spring 管理。
我在我的控制器上使用@PostConstruct 初始化我的应用程序。 在 PostConstruct 中,我所有的 daos 都运行良好,但是当我通过按下 JavaFX 按钮调用服务来保存某些内容时,我得到了这个异常。
Caused by: org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is java.lang.IllegalStateException: EntityManagerFactory is closed
at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:431)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:463)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:276)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy48.saveGame(Unknown Source)
at dev.debizis.mtggui.desktop.controller.TemplateEditorController.handleSaveGameAction(TemplateEditorController.java:362)
... 68 more
Caused by: java.lang.IllegalStateException: EntityManagerFactory is closed
at org.hibernate.jpa.internal.EntityManagerFactoryImpl.validateNotClosed(EntityManagerFactoryImpl.java:388)
at org.hibernate.jpa.internal.EntityManagerFactoryImpl.internalCreateEntityManager(EntityManagerFactoryImpl.java:342)
at org.hibernate.jpa.internal.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:313)
at org.springframework.orm.jpa.JpaTransactionManager.createEntityManagerForTransaction(JpaTransactionManager.java:449)
at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:369)
... 76 more
有谁知道为什么 entityManager 不在方法上使用 @Transactonal 打开事务?
我的休眠 bean 配置:
http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd">
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<!-- the property configurer for the datasource -->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>jdbc.properties</value>
</list>
</property>
<property name="ignoreUnresolvablePlaceholders" value="true" />
</bean>
<!-- the DataSource (parameterized for configuration via a PropertyPlaceHolderConfigurer) -->
<bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp2.BasicDataSource">
<property name="driverClassName" value="${h2.jdbc.driverClassName}" />
<property name="url" value="${h2.jdbc.url}" />
<property name="username" value="${h2.jdbc.username}" />
<property name="password" value="${h2.jdbc.password}" />
</bean>
<!-- Hibernate SessionFactory Definition Debug -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.cardassiel.dao.entity" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.connection.autocommit">false</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.H2Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">validate</prop>
<prop key="hibernate.bytecode.use_reflection_optimizer">true</prop>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider</prop>
<!-- <prop key="hibernate.enable_lazy_load_no_trans">true</prop> -->
</props>
</property>
</bean>
<!-- Hibernate Transaction Manager Definition -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
我的服务环境
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<import resource="classpath*:dao-context.xml" />
<import resource="classpath*:common-context.xml" />
<context:component-scan base-package="com.cardassiel.core.service" />
<context:component-scan base-package="com.cardassiel.core.mapper" />
<!-- hibernate transaction by annotations -->
<tx:annotation-driven transaction-manager="transactionManager" />
我的保存方式:
/** {@inheritDoc} */
@Override
@Transactional
public final Long saveGame(final GameDTO game) {
LOGGER.debug("saveGame : name = {}", game.getName());
return gameDao.saveOrUpdate(mapper.map(game, Game.class));
}
我的道法:
/** {@inheritDoc}*/
@SuppressWarnings("unchecked")
@Override
public final P saveOrUpdate(final T o) {
if (entityManager.getEntityManagerFactory().getPersistenceUnitUtil().getIdentifier(o) == null) {
entityManager.persist(o);
} else {
entityManager.merge(o);
}
return (P) entityManager.getEntityManagerFactory().getPersistenceUnitUtil().getIdentifier(o);
}
提前致谢。
通过阅读日志,我明白了发生了什么。
一个线程正在关闭 applicationContext,并隐含地关闭所有单例 bean,包括 entityManagerFactory!
entityManagerFactory 在每个 PersistenceUnit 生命周期中只能打开一次。
当 Transaction 尝试打开带有关闭工厂的 entityManager 时,它会抛出异常。