java javax.persistence.TransactionRequiredException: 没有 EntityManager 与当前线程可用的实际事务
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/43901381/
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
javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread
提问by studentST
I created my first Spring MVC project with using Hibernate. My DAO layer is using JPA EntityManager for interaction with database.
我使用 Hibernate 创建了我的第一个 Spring MVC 项目。我的 DAO 层使用 JPA EntityManager 与数据库进行交互。
GenericDao.java:
GenericDao.java:
@Repository
public abstract class GenericDao<T> implements GeneralDao<T> {
private Class<T> className;
public GenericDao(Class<T> className) {
this.className = className;
}
@PersistenceContext
private EntityManager entityManager;
public EntityManager getEntityManager() {
return entityManager;
}
@Override
public void add(T object) {
try {
getEntityManager().persist(object);
} catch (HibernateException e) {
throw new DaoException(ErrorMessage.ADD_ENTITY_FAIL, e);
}
}
@Override
public void update(T object) {
try {
getEntityManager().merge(object);
} catch (HibernateException e) {
throw new DaoException(ErrorMessage.UPDATE_ENTITY_FAIL, e);
}
}
@Override
public void remove(T object) {
try {
getEntityManager().remove(object);
} catch (HibernateException e) {
throw new DaoException(ErrorMessage.REMOVE_ENTITY_FAIL, e);
}
}
@Override
public T getById(int id) {
try {
return getEntityManager().find(this.className, id);
} catch (HibernateException e) {
throw new DaoException(ErrorMessage.GET_BY_ID_ENTITY_FAIL, e);
}
}
public abstract List<T> getAll() throws DaoException;
}
GenericService.java
通用服务.java
@Service
public abstract class GenericService<T> implements GeneralService<T> {
private static Logger logger = Logger.getLogger(GenericService.class);
@Autowired
private GenericDao<T> dao;
@Transactional
@Override
public void add(T object) throws ServiceException {
try {
dao.add(object);
} catch (DaoException e) {
logger.debug(e);
throw new ServiceException(e.getMessage());
}
}
@Transactional
@Override
public void update(T object) throws ServiceException {
try {
dao.update(object);
} catch (DaoException e) {
logger.debug(e);
throw new ServiceException(e.getMessage());
}
}
@Transactional
@Override
public void remove(T object) throws ServiceException {
try {
dao.remove(object);
} catch (DaoException e) {
logger.debug(e);
throw new ServiceException(e.getMessage());
}
}
@Transactional(readOnly = true)
@Override
public T getById(int id) throws ServiceException {
try {
return dao.getById(id);
} catch (DaoException e) {
logger.debug(e);
throw new ServiceException(e.getMessage());
}
}
@Transactional(readOnly = true)
@Override
public List<T> getAll() throws ServiceException {
try {
return dao.getAll();
} catch (DaoException e) {
logger.debug(e);
throw new ServiceException(e.getMessage());
}
}
}
UserServiceImpl.java:
UserServiceImpl.java:
@Service
public class UserServiceImpl extends GenericService<User> implements UserService {
private static Logger logger = Logger.getLogger(UserServiceImpl.class);
@Autowired
private UserDao userDao;
@Transactional
@Override
public String checkUser(String userLogin, String userPassword) throws ServiceException {
String namePage = "errorAuthorization";
List<User> userList;
try {
userList = userDao.getByLoginAndPassword(userLogin, userPassword);
} catch (DaoException e) {
logger.debug(e);
throw new ServiceException(e.getMessage());
}
if(userList.size() != 0) {
return UserRoleChecker.defineUserPage(userList.get(0));
}
return namePage;
}
@Transactional
@Override
public void addUser(String userLogin, String userPassword, String userMail) throws ServiceException {
Role role = new Role(0L, RoleType.USER);
User user = new User(0L, userLogin, userPassword, userMail, role);
add(user);
}
}
UserController.java:
用户控制器.java:
@Controller
public class UserController {
private static String className = UserController.class.getName();
private static Logger logger = Logger.getLogger(UserController.class.getName());
@Autowired
private UserService userService;
@RequestMapping(value = "/check_user", method = RequestMethod.POST)
public ModelAndView authorizationUser(HttpServletRequest request, HttpServletResponse response) {
ModelAndView modelAndView = new ModelAndView();
String returnPage;
try {
returnPage = userService.checkUser(request.getParameter(RequestParameter.USER_LOGIN), request.getParameter(RequestParameter.USER_PASSWORD));
} catch (ServiceException e) {
logger.debug(e);
returnPage = ErrorHandler.returnErrorPage(e.getMessage(), className);
}
modelAndView.setViewName(returnPage);
return modelAndView;
}
@RequestMapping(value = "/add_user", method = RequestMethod.POST)
public ModelAndView registrationUser(HttpServletRequest request, HttpServletResponse response) {
ModelAndView modelAndView = new ModelAndView();
String returnPage = Page.SUCCESSFUL_REGISTRATION;
try {
userService.addUser(request.getParameter(RequestParameter.USER_LOGIN), request.getParameter(RequestParameter.USER_PASSWORD), request.getParameter(RequestParameter.USER_MAIL));
} catch (ServiceException e) {
logger.debug(e);
returnPage = ErrorHandler.returnErrorPage(e.getMessage(), className);
}
modelAndView.setViewName(returnPage);
return modelAndView;
}
}
root-context.xml:
根上下文.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:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.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">
<context:annotation-config />
<context:component-scan base-package="by.netcracker.artemyev.dao" />
<context:component-scan base-package="by.netcracker.artemyev.service" />
<context:component-scan base-package="by.netcracker.artemyev.web" />
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
<property name="url" value="jdbc:mysql://localhost:3306/airline?useSSL=false" />
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
<property name="initialSize" value="5"/>
<property name="maxTotal" value="10"/>
</bean>
<bean id="entityManager" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="by.netcracker.artemyev" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="database" value="MYSQL" />
<property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect" />
</bean>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="debug">true</prop>
<prop key="connection.isolation">2</prop>
<prop key="hibernate.cglib.use_reflection_optimizer">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
<property name="jpaDialect" ref="jpaDialect" />
</bean>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManager" />
<property name="dataSource" ref="dataSource" />
<property name="jpaDialect" ref="jpaDialect" />
</bean>
</beans>
Logs:
日志:
org.springframework.web.servlet.FrameworkServlet 2017-05-10 22:23:59,107 DEBUG - Could not complete request
javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'persist' call
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:282)
at com.sun.proxy.$Proxy27.persist(Unknown Source)
at by.netcracker.artemyev.dao.GenericDao.add(GenericDao.java:35)
at by.netcracker.artemyev.service.GenericService.add(GenericService.java:24)
at by.netcracker.artemyev.service.impl.UserServiceImpl.addUser(UserServiceImpl.java:48)
at by.netcracker.artemyev.web.UserController.registrationUser(UserController.java:45)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:661)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:475)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:624)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:341)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:495)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:767)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1354)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Why I have this problem and how to fix it?
为什么我有这个问题以及如何解决它?
回答by Vikram S
I resolved it by adding @Transactionalannotation above the controller/service.
我通过在控制器/服务上方添加@Transactional注释来解决它。
回答by abaghel
You have shown root-context.xml
in your question but this context file doesn't have ViewResolver bean configuration. You must be having servlet context configuration file for Dispatcher Servlet (e.g. dispatcher-servlet.xml) configured in web.xml
. Please add following configuration to your dispatcher-servlet.xml
.
您已root-context.xml
在问题中显示,但此上下文文件没有 ViewResolver bean 配置。您必须在web.xml
. 请将以下配置添加到您的dispatcher-servlet.xml
.
<tx:annotation-driven />
If you don't have xmlns:tx
definition in your dispatcher-servlet.xml
like other xmlns:
definitions, then add it. Please make sure you have proper configuration for component-scan in dispacher servlet context.
如果您xmlns:tx
在dispatcher-servlet.xml
其他xmlns:
定义中没有定义,则添加它。请确保您在调度程序 servlet 上下文中对组件扫描进行了正确的配置。
<context:component-scan base-package="by.netcracker.artemyev.*" />
You can also refer to post @Transactional doesn't work in Spring Web MVC?where similar issue has been reported.
您还可以参考帖子@Transactional 在 Spring Web MVC 中不起作用?已报告类似问题的地方。
回答by Andrew
I encounter this issue when maintaining a legacy code, finally I realised from complex annotations.
我在维护遗留代码时遇到了这个问题,最后我从复杂的注释中意识到。
it needs @EnableTransactionManagement on app level. otherwise @Transactional is not working
它需要应用程序级别的@EnableTransactionManagement。否则@Transactional 不起作用