Java Spring JPA 没有正在进行的事务
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28950134/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring JPA no transaction is in progress
提问by Misha Akopov
I am new to Spring and JPA, wasted 5 days and no result with searching internet. I want to save object to SQL SERVER, connection is correct but when I write .flush() I get the exception
我是 Spring 和 JPA 的新手,浪费了 5 天,搜索互联网没有结果。我想将对象保存到 SQL SERVER,连接是正确的,但是当我编写 .flush() 时出现异常
nested exception is javax.persistence.TransactionRequiredException: no transaction is in progress
嵌套异常是 javax.persistence.TransactionRequiredException: no transaction is in progress
This is my jpaContext.xml
这是我的 jpaContext.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/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
<context:annotation-config />
<context:component-scan base-package="com.misha.service"/>
<context:component-scan base-package="com.misha.repository"/>
<context:component-scan base-package="com.misha.model"/>
<bean
class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean id="myEntityManager"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.misha.model"/>
<property name="persistenceUnitName" value="test" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop>
</props>
</property>
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="net.sourceforge.jtds.jdbc.Driver" />
<property name="url"
value="jdbc:jtds:sqlserver://127.0.0.1;instance=SQLEXPRESS;DatabaseName=misha" />
<property name="username" value="sa" />
<property name="password" value="root" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="myEntityManager" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
This is my persistence.xml file:
这是我的 persistence.xml 文件:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" 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">
<persistence-unit name="test" >
<class>com.misha.model.Table1</class>
</persistence-unit>
</persistence>
This is my Service implementation:
这是我的服务实现:
@Service("manService")
public class SaveManImpl implements SaveMan {
//
@Autowired
private ManRepositoryImpl manRepo;
@Transactional
public Table1 save(Table1 table) {
manRepo.save(table);
return null;
}
}
And finally my Repository implementation:
最后是我的存储库实现:
@Repository("manRepository")
public class ManRepositoryImpl implements ManRepository {
@PersistenceContext
private EntityManager em;
public Table1 save(Table1 table){
em.persist(table);
em.flush();
return table;
}
}
From the exception, Spring cant see @Transactional annotation, am I right ? I tried to put the annotation above repository save method, no result, after this above Service save method, the same here. Thanks in advance
从例外情况来看,Spring 看不到 @Transactional 注释,对吗?我试着把注解放在repository save方法上面,没有结果,经过上面的Service save方法,这里也是一样。提前致谢
I call the save method in my Controller
我在控制器中调用 save 方法
package com.misha.controllers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import com.misha.model.Table1;
import com.misha.service.SaveMan;
@Controller
public class ManController {
@Autowired
SaveMan saveMan; // this is service interface
@RequestMapping(value="/test1")
public String saveMan(){
Table1 tab = new Table1();
tab.setName("name");
saveMan.save(tab);
return "saveMan";
}
}
Error stack:
错误堆栈:
SEVERE: Servlet.service() for servlet [fitTrackerServlet] in context with path [/test] threw exception [Request processing failed; nested exception is javax.persistence.TransactionRequiredException: no transaction is in progress] with root cause
javax.persistence.TransactionRequiredException: no transaction is in progress
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.checkTransactionNeeded(AbstractEntityManagerImpl.java:1171)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:1332)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:365)
at com.sun.proxy.$Proxy20.flush(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:240)
at com.sun.proxy.$Proxy20.flush(Unknown Source)
at com.misha.repository.ManRepositoryImpl.save(ManRepositoryImpl.java:21)
at com.misha.service.SaveManImpl.save(SaveManImpl.java:19)
at com.misha.controllers.ManController.saveMan(ManController.java:21)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:175)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:421)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:409)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:774)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:618)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:725)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:537)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1085)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:658)
at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:222)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1556)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1513)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Unknown Source)
Spring configuration file
弹簧配置文件
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.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">
<mvc:annotation-driven />
<!--<mvc:resources location="pdfs" mapping="/pdfs/**" />
<mvc:resources location="/resources" mapping="/resources/**"/> -->
<context:component-scan base-package="com.misha.controllers"></context:component-scan>
<context:component-scan base-package="com.misha.repository" />
<context:component-scan base-package="com.misha.service" />
<context:annotation-config/>
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"></property>
<property name="suffix" value=".jsp"></property>
<property name="order" value="0"></property>
</bean>
<bean id="contentNegotiatingViewResolver"
class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="order" value="1" />
<property name="mediaTypes">
<map>
<entry key="json" value="application/json" />
<entry key="xml" value="application/xml" />
<entry key="request" value="text/html" />
</map>
</property>
<property name="favorPathExtension" value="false" />
<property name="favorParameter" value="true" />
<property name="defaultViews">
<list>
</list>
</property>
</bean>
<bean class="org.springframework.context.support.ResourceBundleMessageSource" >
<property name="basename" value="WEB-INF/messages"></property>
</bean>
</beans>
采纳答案by JB Nizet
You have two Spring contexts:
您有两个 Spring 上下文:
the main one, configured by jpaContext.xml, where beans from the service and repository packages are scanned, and proxied by a transactional interceptor.
the mvc one, configured by the other xml file (you didn't name it) whose role is to describe the MVC part of the application, i.e. define and configure for example the controller beans, the view resolver, etc. This context is a child of the main one.
主要的,由 jpaContext.xml 配置,其中来自服务和存储库包的 bean 被扫描,并由事务拦截器代理。
mvc 一个,由另一个 xml 文件(您没有命名)配置,其作用是描述应用程序的 MVC 部分,即定义和配置例如控制器 bean、视图解析器等。这个上下文是一个主要的孩子。
The problem is that you also scan the service and repository packages in this child context. You thus end up with two instances of each service and repository:
问题是您还扫描了此子上下文中的服务和存储库包。因此,您最终会得到每个服务和存储库的两个实例:
- one in the main context, which is transactional
- one in the child context, which is not (since the child context doesn't care about transaction management)
- 一个在主要上下文中,这是事务性的
- 一个在子上下文中,不是(因为子上下文不关心事务管理)
The controller is thus injected with a service coming from the same context as the controller: the not transactional one.
因此,控制器被注入来自与控制器相同的上下文的服务:非事务性的。
To confirm that, you could add traces in the constructor of the beans and see how many times they are instantiated.
为了确认这一点,您可以在 bean 的构造函数中添加跟踪并查看它们被实例化的次数。
And to avoid the problem, there are two solutions:
为了避免这个问题,有两种解决方案:
- avoid scanning the repository and service packages in the mvc context: this context should only care about mvc-related beans. When Spring injects a service in a controller, it would thus not find the service in the mvc context, and thus look it up, and find it in the main context. The transactional service would thus be injected.
- use a single context: the one of the servlet, where all the beans in the application would be defined.
- 避免扫描 mvc 上下文中的存储库和服务包:这个上下文应该只关心 mvc 相关的 bean。当 Spring 在控制器中注入服务时,它因此不会在 mvc 上下文中找到该服务,从而查找它,并在主上下文中找到它。事务服务将因此被注入。
- 使用单个上下文:servlet 中的一个上下文,其中将定义应用程序中的所有 bean。
回答by karthik manchala
You should introduce your entity manager to your transaction manager, so that when you annotate your function with @Transactional
it loads instances from the pool
你应该将你的实体管理器引入你的事务管理器,这样当你用@Transactional
它来注释你的函数时,它会从池中加载实例
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="myEmf" />
</bean>
<tx:annotation-driven />
HTH!
哼!
回答by Damir Olejar
To make the story short, try adding @Transactional
at the very beginning of your method. That was an issue in my case.
为了使故事简短,请尝试@Transactional
在方法的开头添加 。就我而言,这是一个问题。