2017-01-17 4 views
3

Некоторая справочная информация: Я пытаюсь перенести большой проект из Hibernate 3.6.8 в 5.2.5 (включая обновление JPA 2.0 до 2.1) Весна 3.2.3 - 4.3.5, и я столкнулся с серьезными проблемами. Конфигурация не была изменена для Spring и Hibernate до сих пор и отлично работает на старых версиях, однако с проблемами обновления, которые я не могу решить самостоятельно, возникла.Отсутствует EntityManager с реальной транзакцией, доступной для текущего потока - не может надежно обрабатывать вызов «flush»

Исключение я получаю:

2017-01-16 10:15:25,635 ERROR [[ACTIVE] ExecuteThread: '15' for queue: 'weblogic.kernel.Default (self-tuning)'] org.myproject.common.messaging.BaseMDB: Code: (11702) Source: (Common) Exception caught - Exception org.springframework.dao.InvalidDataAccessApiUsageException in org.myproject.core.processing.message.MessageReceiverImpl caught 
org.springframework.dao.InvalidDataAccessApiUsageException: No EntityManager with actual transaction available for current thread - cannot reliably process 'flush' call; nested exception is javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'flush' call 
       at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:413) 
       at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:246) 
       at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:491) 
       at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59) 
       at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213) 
       at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147) 
       at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
       at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) 
       at com.sun.proxy.$Proxy187.flushAndClear(Unknown Source) 
       at org.myproject.core.BasePersistenceMDB.synchronizeBackend(BasePersistenceMDB.java:46) 
       at org.myproject.core.BasePersistenceMDB.onTextMessage(BasePersistenceMDB.java:32) 
       at org.myproject.common.messaging.BaseMDB.evaluateJMSMessage(BaseMDB.java:100) 
       at org.myproject.common.messaging.BaseMDB.onMessage(BaseMDB.java:51) 
       at sun.reflect.GeneratedMethodAccessor591.invoke(Unknown Source) 
       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
       at java.lang.reflect.Method.invoke(Method.java:498) 
       at com.bea.core.repackaged.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:310) 
       at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182) 
       at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149) 
       at com.oracle.pitchfork.intercept.MethodInvocationInvocationContext.proceed(MethodInvocationInvocationContext.java:100) 
       at com.oracle.pitchfork.intercept.JeeInterceptorInterceptor.invoke(JeeInterceptorInterceptor.java:117) 
       at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171) 
       at com.bea.core.repackaged.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131) 
       at com.bea.core.repackaged.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:119) 
       at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171) 
       at com.bea.core.repackaged.springframework.aop.framework.JdkDynamicAopProxy.invoke(Unknown Source) 
       at com.sun.proxy.$Proxy121.onMessage(Unknown Source) 
       at weblogic.ejb.container.internal.MDListener.execute(MDListener.java:451) 
       at weblogic.ejb.container.internal.MDListener.transactionalOnMessage(MDListener.java:375) 
       at weblogic.ejb.container.internal.TokenBasedJMSMessagePoller.processOneMessage(TokenBasedJMSMessagePoller.java:279) 
       at weblogic.ejb.container.internal.TokenBasedJMSMessagePoller.run(TokenBasedJMSMessagePoller.java:121) 
       at weblogic.work.SelfTuningWorkManagerImpl$WorkAdapterImpl.run(SelfTuningWorkManagerImpl.java:548) 
       at weblogic.work.ExecuteThread.execute(ExecuteThread.java:311) 
       at weblogic.work.ExecuteThread.run(ExecuteThread.java:263) 
Caused by: javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'flush' call 
       at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:282) 
       at com.sun.proxy.$Proxy163.flush(Unknown Source) 
       at org.myproject.core.data.dao.impl.MyPersistenceContextImpl.flushAndClear(MyPersistenceContextImpl.java:49) 
       at sun.reflect.GeneratedMethodAccessor616.invoke(Unknown Source) 
       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
       at java.lang.reflect.Method.invoke(Method.java:498) 
       at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333) 
       at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) 
       at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) 
       at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136) 
       ... 28 more 

Моя конфигурация выглядит следующим образом: pom.xml (соответствующие фрагменты): для весны:

<dependency> 
    <groupId>org.springframework</groupId> 
    <artifactId>spring-context</artifactId> 
    <version>4.3.5.RELEASE</version> 
    </dependency> 
    <dependency> 
    <groupId>org.springframework</groupId> 
    <artifactId>spring-context-support</artifactId> 
    <version>4.3.5.RELEASE</version> 
    </dependency> 
    <dependency> 
    <groupId>org.springframework</groupId> 
    <artifactId>spring-core</artifactId> 
    <version>4.3.5.RELEASE</version> 
    </dependency> 
    <dependency> 
    <groupId>org.springframework</groupId> 
    <artifactId>spring-jdbc</artifactId> 
    <version>4.3.5.RELEASE</version> 
    </dependency> 
    <dependency> 
    <groupId>org.springframework</groupId> 
    <artifactId>spring-orm</artifactId> 
    <version>4.3.5.RELEASE</version> 
    </dependency> 
    <dependency> 
    <groupId>org.springframework</groupId> 
    <artifactId>spring-tx</artifactId> 
    <version>4.3.5.RELEASE</version> 
    </dependency> 
    <dependency> 
    <groupId>org.springframework</groupId> 
    <artifactId>spring-web</artifactId> 
    <version>4.3.5.RELEASE</version> 
    </dependency> 
    <dependency> 
    <groupId>org.springframework</groupId> 
    <artifactId>spring-webmvc</artifactId> 
    <version>4.3.5.RELEASE</version> 
    </dependency> 
    <dependency> 
    <groupId>org.springframework</groupId> 
    <artifactId>spring-test</artifactId> 
    <version>4.3.5.RELEASE</version> 
    <scope>test</scope> 
    </dependency> 

для Hibe rnate:

<dependency> 
     <groupId>org.hibernate.common</groupId> 
     <artifactId>hibernate-commons-annotations</artifactId> 
     <version>5.0.1.Final</version> 
     </dependency> 
     <dependency> 
     <groupId>org.hibernate</groupId> 
     <artifactId>hibernate-core</artifactId> 
     <version>5.2.6.Final</version> 
     </dependency> 
     <dependency> 
     <groupId>org.hibernate</groupId> 
     <artifactId>hibernate-entitymanager</artifactId> 
     <version>5.2.6.Final</version> 
     </dependency> 
    <dependency> 
     <groupId>org.hibernate.javax.persistence</groupId> 
     <artifactId>hibernate-jpa-2.1-api</artifactId> 
     <version>1.0.0.Final</version> 
     </dependency> 
     <dependency> 
     <groupId>org.hibernate</groupId> 
     <artifactId>hibernate-jpamodelgen</artifactId> 
     <version>5.2.6.Final</version> 
     <scope>provided</scope> 
     </dependency> 

persistence.xml (полный): (здесь некоторые вещи, которые были изменены, но не помогли: JTA-источники данных были добавлены, версии XSD были обновлены)

<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd" 
      version="2.1"> 

    <persistence-unit name="MYPROJECT_PU" transaction-type="JTA">   
     <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider> 
     <jta-data-source>myproject-ds_jndi</jta-data-source> 

     <mapping-file>META-INF/named-queries.xml</mapping-file> 

     <class>org.myproj.core.domain.Message</class> 

    </persistence-unit> 

</persistence> 

appContext.xml (соответствующие фрагменты): (только что добавили еще одно дополнительное свойство в jpaProperties с момента обновления)

<?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:context="http://www.springframework.org/schema/context" 
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jdbc="http://www.springframework.org/schema/jdbc" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans.xsd 
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context.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" /> 

    <bean 
     class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" /> 

    <bean 
     class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> 
     <property name="locations"> 
      <list> 
       <value>classpath:configuration.properties</value> 
       <value>classpath:externalized-queries.properties</value> 
      </list> 
     </property> 
    </bean> 

    <bean id="jndiDataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> 
     <property name="jndiName" value="${datasourceJndiName}"></property> 
    </bean> 

    <!-- Indicates a JpaVendorAdapter implementation for Hibernate EntityManager. --> 
    <bean id="jpaVendorAdapter" 
     class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> 
     <property name="database" value="${databaseVendor}" /> 
     <property name="showSql" value="${showSql}" /> 
     <property name="generateDdl" value="${generateDdl}" /> 
     <property name="databasePlatform" value="${databaseDialect}" /> 
    </bean> 

    <bean id="entityManagerFactory" 
     class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
     <property name="persistenceXmlLocation" value="${persistenceXmlFileLocation}" /> 
     <property name="persistenceUnitName" value="${persistenceUnitName}" /> 
     <property name="dataSource" ref="jndiDataSource" /> 
     <property name="jpaVendorAdapter" ref="jpaVendorAdapter" /> 
     <property name="jpaProperties"> 
      <props> 
       <prop key="hibernate.transaction.manager_lookup_class">${transactionManagerLookupClass}</prop> 
       <prop key="hibernate.transaction.jta.platform">org.hibernate.service.jta.platform.internal.WeblogicJtaPlatform</prop> <!-- this was newly added --> 

      </props> 
     </property> 
    </bean> 

    <tx:annotation-driven /> 

    <tx:jta-transaction-manager /> 

... 

Соответствующие фрагменты из класса, который открывает сделки, демонстрирующие, какие аннотаций были использованы здесь:

import java.sql.SQLException; 
import java.util.Set; 

import javax.interceptor.Interceptors; 

import org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor; 
import org.springframework.transaction.annotation.Propagation; 
import org.springframework.transaction.annotation.Transactional; 

... 

@Interceptors(SpringBeanAutowiringInterceptor.class) 
@Transactional(propagation = Propagation.REQUIRED) 
public class DBLockingImpl implements Locking { 

@Autowired 
private DataSource dataSource; 

Это класс вызова EntityManager (транзакция уже открыта в данный момент, но исключение происходит, когда вровень метод вызывается на EntityManager здесь):

import javax.persistence.EntityManager; 
import javax.persistence.PersistenceContext; 

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Repository; 


@Repository(value = "persistenceContext") 
public class PersistenceContextImpl 
    implements PersistenceContext { 

    /** 
    * Instance variable for EntityManager. 
    */ 
    @PersistenceContext 
    private EntityManager entityManager; 

    @Override 
    public void flushAndClear() { 
     entityManager.flush(); 
     entityManager.clear(); 
    } 
} 

Так может кто-нибудь, пожалуйста, помогите мне с этим вопросом? Я не понимаю, чего не хватает и почему я получаю это исключение. У меня создается впечатление, что Spring не подключается должным образом к администратору сущности Hibernates, и поэтому возникает исключение, поскольку сам процесс трансляции создается, но всякий раз, когда он пытается сохранить это исключение, мухи. В конце концов, мне кажется странным, что он больше не работает, хотя он отлично работал со старыми версиями этих фреймворков. Были ли большие изменения в конфигурации из старых версий?

+0

Я озадачен классом '' PersistenceContextImpl''', почему бы вам переопределить аннотацию PersistenceContext? Весной внедренный EntityManager является прокси-сервером, который взаимодействует с хранилищем Transactional и ThreadLocal, и почти так же, как аннотация Transactional не соблюдается. Я думаю, вам будет очень повезло, если кто-то еще попробовал это раньше и знает причину. Я боюсь, что вам придется отлаживать эту цифру. –

+0

И если вы уже обновляете проект, вы не избавитесь от Maven и раздутой конфигурации XML и сделаете переход на Gradle;) –

+0

@KlausGroenbaek. Мне жаль, что вас не смущает, PersistenceContextImpl в этом случае не переопределяет PersistenceContext, но это обычный класс, который используется и который имеет некоторое взаимодействие с базой данных. И спасибо за информацию о Gradle;) Я буду проверять Gradle в будущем, но я уверен, что переход от Maven к Gradle на данный момент будет довольно летальным ...: D – ProgEngineer

ответ

0

Я подозреваю, что это может быть проблемой при сканировании компонентов или сканировании пакетов. Я не могу найти код сканирования пакета в вашем конфигурационном файле весны. Проверьте это или обновите конфигурационный файл.

0

Сканирование, похоже, работает. Если вы посмотрите на стек, вы можете увидеть EntityManager Proxy (com.sun.proxy. $ Proxy163) и переместить его до SharedEntityManagerCreator, как и ожидалось.

Однако перед созданием SharedEntityManager он проверяет, есть ли транзакция, и эта проверка завершилась с ошибкой. Сделка должна быть создана аннотацией @Transactional.Это происходит через Spring AOP, либо создавая прокси-сервер GCLIB, расширяющий DBLockingImpl, либо прокси-сервер JDK, реализующий Locking. Это можно определить, установив точку останова внутри метода и посмотрев на столбец, чтобы узнать, как был вызван метод.

Глядя на DBLockingImpl Я заметил, что вы используете SpringBeanAutowiringInterceptor, что говорит о том, что DBLockingImpl не является фасолью Spring, но вы просто запустили в него весенние бобы. Если это тот случай, то я думаю, что это ваша проблема, потому что тогда DBLockingImpl не будет проксирована AOP, поэтому @Transactional не будет применяться.

Попробуйте сделать DBLockingImpl фасоль.

Смежные вопросы

 Смежные вопросы