原文地址:
springMVC和spring各自扫描自己的注解不要相互混淆(entityManager.flush()报错no transaction is in progress)_pucao_cug的专栏-CSDN博客_entitymanager no transaction is in progress
https://blog.csdn.net/pucao_cug/article/details/50359896?fps=1&locationNum=16
springMVC和spring各自扫描自己的注解不要相互混淆(entityManager.flush()报错no transaction is in progress)
1、问题
执行 entityManager.flush(); 总是报错:javax.persistence.TransactionRequiredException: no transaction is in progress
字面解释是:“没有启动事务”。可是事务是在配置中交给了spring管理了,在方法上加注解 @Transactional就申明了事务的,而且配置中也启动事务注解的扫描:
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>,为何说没有启动事务呢?
2、原因
折腾了很久,分析了很久,也看了一些文章,都没说在关键上,后来有一个文章受到启发,虽然讲的不是我报错的这个问题,但是隐约感觉到问题应该是spring注解管理器和springMVC注解管理器是不同的,他们各自有自己能识别和管理的一堆注解。我的问题出在让springMVC注解管理器扫描了不该他自己管的注解了,例如spring申明式事物相关的注解@Transactional就不该让springMVC来扫描,springMVC注解管理器让他来扫描controller类里面的东西就好了,不要让他来和spring的其他注解掺和。
3、解决
让springMVC的配置xml和spring容器的配置xml分开(虽然让这两个文件分开不是必须的,但是分开是为了看着清爽,也更便于维护)。分开之后,在spring和springMVC各自的xml中配置自己功能相关的东西,不要让springMVC去扫描不该自己管理的那些注解。
3.1 springMVC部分
3.1.1 web.xml 中 springMVC相关部分
<servlet>
<servlet-name>springMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
3.1.2 mvc.xml 文件中关键部分
<!-- 开启springMVC注解支持 -->
<mvc:annotation-driven/>
<mvc:default-servlet-handler/>
<!-- 扫描Controller -->
<context:component-scan base-package="org.cj.controller">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
</context:component-scan>
3.2 spring容器部分
spring容器需要扫描的注解,放在别的xml中,让spring 的Listener去解读
3.2.1 web.xml 中spring容器关键部分
<context-param>
<param-name>contextConfigLocation</param-name>
<!--说明:需要让spring 容器解读的配置,放在spring-开头的xml文件中 -->
<param-value> /WEB-INF/spring-*.xml </param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
3.2.2 spring-core.xml文件关键部分
<!--扫描org.cj所有子目录的spring注解-->
<context:component-scanbase-package="org.cj"/>
<!--开启spring的事务申明注解支持,开启对class的动态代理功能,这个非常关键,不能少-->
<tx:annotation-driventransaction-manager="transactionManager"proxy-target-class="true"/>
原文截图: