TransactionRequiredException, выдаваемая EclipseLink 2.4.1 при использовании Spring 3.1.3
Я пытаюсь настроить следующие компоненты:
- EclipseLink 2.4.1
- Весна 3.1.3
- Glassfish 3.1.2
- Derby Embedded Database
материал работает до сих пор. но как только я хочу что-то сохранить в своем контексте JPA, TransactionRequiredException
брошен:
javax.persistence.TransactionRequiredException:
Exception Description: No transaction is currently active
at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionWrapper.throwCheckTransactionFailedException(EntityTransactionWrapper.java:113)
at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionWrapper.checkForTransaction(EntityTransactionWrapper.java:50)
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.checkForTransaction(EntityManagerImpl.java:1776)
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.flush(EntityManagerImpl.java:780)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:365)
at $Proxy439.flush(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:240)
at $Proxy439.flush(Unknown Source)
at backend.dao.StoredObjectDAO.save(StoredObjectDAO.java:39)
at backend.service.StorageService.setObjectForKey(StorageService.java:35)
at backend.controller.StoredObjectController.setObjectForKey(StoredObjectController.java:40)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:219)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:100)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:604)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:565)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:688)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:770)
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1542)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:281)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:161)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:331)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231)
at com.sun.enterprise.v3.services.impl.ContainerMapper$AdapterCallable.call(ContainerMapper.java:317)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:195)
at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:849)
at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:746)
at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1045)
at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:228)
at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
at java.lang.Thread.run(Thread.java:680)
диспетчер транзакций настраивается, как описано в различных руководствах, и даже Eclipse распознает соткание аспектов j, указывая контрольные точки с соответствующими значками рядом с панелью белья. так как я использую @Transactional
аннотация, я правильно настроил <tx:annotaion-driven />
на "на".
но все же я продолжаю получать одно и то же исключение. Кто-нибудь знает, нужна ли особая настройка при использовании этого набора библиотек? пожалуйста, найдите все необходимые файлы, прикрепленные ниже.
спасибо ману
ОБНОВИТЬ
наконец-то покинул Spring и использовал другой стек:
- Google Guice (внедрение зависимостей)
- Джерси (библиотека REST)
- Eclipse Link (JPA)
Я должен был идти дальше, и это решение было более прагматичным в то время. может, дать Весне еще один шанс.
спасибо всем за ваш вклад в любом случае!:-)
ApplicationContext-jpa.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:context="http://www.springframework.org/schema/context"
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-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<context:load-time-weaver />
<context:annotation-config />
<tx:annotation-driven transaction-manager="transactionManager" />
<import resource="applicationContext-dataSource.xml" />
<bean id="jpaAdapter" class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
<property name="databasePlatform" value="org.eclipse.persistence.platform.database.DerbyPlatform" />
<property name="showSql" value="true" />
</bean>
<bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect" />
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter" ref="jpaAdapter" />
<property name="persistenceXmlLocation" value="classpath:/META-INF/persistence.xml"/>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="dataSource" ref="dataSource" />
<property name="jpaDialect" ref="jpaDialect" />
</bean>
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
</beans>
ApplicationContext-dataSource.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:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
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-3.1.xsd">
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/backend" />
</beans>
persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="backend" transaction-type="JTA">
<!--
jta-data-source is only used for the IDE. Spring/Runtime uses the
data source from applicationContext-dataSource.
-->
<jta-data-source>jdbc/backend</jta-data-source>
<class>backend.model.StoredObject</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
</persistence-unit>
</persistence>
StoredObjectDAO.java
@Repository
@Transactional
public class StoredObjectDAO implements IStoredObjectDAO {
@PersistenceContext
private EntityManager entityManager;
@Override
@Transactional(readOnly = true)
public Collection<StoredObject> listAll() {
TypedQuery<StoredObject> query = entityManager.createQuery("select s from StoredObject s", StoredObject.class);
Collection<StoredObject> results = query.getResultList();
return results;
}
@Override
public void save(StoredObject storedObject) {
entityManager.persist(storedObject);
entityManager.flush(); // <---- throws Exception
}
}
8 ответов
Если вы вызываете ваши методы DAO из классов обслуживания, избегайте аннотирования методов DAO @Transactional. Вместо этого аннотируйте ваши методы класса Service транзакционными. Причина этого в том, что вам может потребоваться вызвать несколько методов DAO в рамках одной транзакции. Это может вызвать проблемы, если все ваши методы DAO являются транзакционными. Поэтому, если вы аннотируете свой транзакционный метод обслуживания, вы можете вызывать любое количество методов DAO в рамках одной транзакции.
Если возникает какое-либо исключение, вся транзакция будет откатываться, если вы аннотируете класс обслуживания транзакции.
Отсутствует в использовании readonly
приписать и propagation
Режим. По умолчанию propagation
режим REQUIRED
, Вот почему ваша кодировка будет выглядеть так:
@Transactional(readOnly = true, propagation=Propagation.REQUIRED)
public Collection<StoredObject> listAll() {
......
}
Точка: readonly
соединение будет брошено исключение, когда REQUIRED
режим распространения используется.
Ответ: если вы хотите использовать readonly
соединение, propagation
режим будет SUPPORTS
,
@Transactional(readOnly = true, propagation=Propagation.SUPPORTS)
public Collection<StoredObject> listAll() {
......
}
Для справок: Стратегии транзакций
В данный момент транзакция не активна? значит не начал сущность Транзактон
Ты можешь попробовать
@Override
public void save(StoredObject storedObject) {
entityManager.getTransaction().begin();
entityManager.persist(storedObject);
entityManager.flush(); // <---- throws Exception
}
но держите отдельный метод для начала и фиксации.
Ошибка выглядит так, как будто EclipseLink использует EntityTransactionWrapper вместо JTATransactionWrapper, который я ожидал, если бы настроил использовать JTA, как в случае с этим сообщением: /questions/6251140/spring-eclipselink-jtatransactionmanager-javaxpersistencetransactionrequiredexception
Возможно, вы захотите убедиться, что используемый файл persistence.xml помечен для JTA и является тем, который вы показали, так как это может быть другой файл persistence.xml, который будет добавлен в ваш путь к классам.
Согласно документации Spring, он описывает значение по умолчанию следующим образом:
Атрибут "proxy-target-class" в элементе "tx:annotation-driven" определяет, какие типы транзакционных прокси создаются для классов, аннотированных аннотацией @Transactional. Если для атрибута proxy-target-class установлено значение true, создаются прокси на основе классов. Если proxy-target-class имеет значение false или атрибут не указан, создаются стандартные прокси на основе интерфейса JDK.
Поскольку в вашем случае используются прокси на основе классов, вам необходимо добавить этот атрибут следующим образом:
tx: прокси-объект-класс-управляемый аннотацией = "истина" транзакция-менеджер = "транзакция-менеджер"
Вы даже можете потерять атрибут:
транзакций менеджер = "TransactionManager"
так как это по умолчанию в любом случае.....!
По весенней документации
<tx:annotation-driven/> only looks for @Transactional on beans in the same application context it is defined in.
This means that, if you put <tx:annotation-driven/> in a WebApplicationContext for a DispatcherServlet, it only checks for @Transactional beans in your controllers, and not your services.
Пожалуйста, проверьте, правильно ли вы настроили
Если вы используете транзакцию-тип ="JTA", то в веб-контейнере, например, Tomcat, вам нужно использовать JOTM для управления транзакциями и настроить ее как в Tomcat, так и в Spring.
И еще, в файле persistence.xml вам нужно добавить следующую строку:
<properties>
<property name="eclipselink.target-server" value="org.eclipse.persistence.transaction.jotm.JotmTransactionController"/>
</properties>