我有一个运行j2ee的应用程序,但我决定将代码组织更改为按功能样式而不是我现在使用的逐层样式,这个更改的主要原因是代码导航和模块化,我有这个架构:
我想将其移至:
当我在新架构上运行测试时,一切正常,但是当尝试通过customerHandler使用customerService时,我收到此错误:
没有可用于当前线程的实际事务的EntityManager - 无法可靠地处理'坚持'调用
我尝试将我的类逐个分组到新包中以查看问题是什么,并且它是customerServiceImpl.java,当我将此类移到com.app.customer包之外时,我的应用程序工作正常, applicationContext.xml文件被配置为扫描com.app.customer包,customerDaoImpl和customerServiceImpl有@Transactional注释,我读到dao或服务应该是事务性的但不是两者都是,所以我尝试从任一类中删除这个注释但我仍然得到同样的错误。
这是完整的堆栈跟踪:
Warning: StandardWrapperValve[dispatcher]: Servlet.service() for servlet dispatcher threw exception
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:278)
at com.sun.proxy.$Proxy234.merge(Unknown Source)
at com.app.customer.customerDaoImpl.merge(customerDaoImpl.java:49)
at com.app.customer.customerServiceImpl.store(customerServiceImpl.java:69)
at com.app.customer.customerHandler.store(customerHandler.java:39)
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:221)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:817)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:731)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:968)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:870)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:844)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1682)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:318)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:416)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:283)
at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:459)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:167)
at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:206)
at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:180)
at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:235)
at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:283)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:200)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:132)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:111)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:536)
at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:591)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:571)
at java.lang.Thread.run(Thread.java:745)
我做错了什么?是否可以使用eclipselink JPA的功能样式使用包构建应用程序?
顺便说一句,我可以从数据库中检索客户信息。
编辑:
这是带有原始打包样式的applicationContext.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:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
<bean id="loadTimeWeaver" class="org.springframework.instrument.classloading.glassfish.GlassFishLoadTimeWeaver" />
<bean id="entityManagerFactory" p:persistenceUnitName="app_PU"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
/>
<tx:jta-transaction-manager />
<tx:annotation-driven />
<context:annotation-config/>
<context:component-scan base-package="com.app.dao"/>
<context:component-scan base-package="com.app.service"/>
</beans>
对于新的包装样式我改变了这个:
<context:component-scan base-package="com.app.dao"/>
<context:component-scan base-package="com.app.service"/>
对此:
<context:component-scan base-package="com.app.customer"/>
然后我得到上面提到的错误,但是如果我将com.app.customer包之外的customerServiceImpl.class移动到其原始位置:com.app.service并将applicationContext.xml更改为:
<context:component-scan base-package="com.app.customer"/>
<context:component-scan base-package="com.app.service"/>
我的应用有效。
的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="app_PU" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/appDB</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="eclipselink.target-server" value="SunAS9"/>
<property name="eclipselink.logging.level" value="INFO"/>
</properties>
</persistence-unit>
</persistence>
答案 0 :(得分:0)
事实证明,当Controller,Service和DAO类在同一个包中时,从Controller对象到Service对象的任何方法调用都被Spring视为自调用调用,这就是为什么没有事务行为被添加到持久化,合并或删除方法中,它还解释了为什么应用程序在将ServiceImpl或DaoImpl类移动到不同的包时工作,因为任何方法调用都被视为外部调用并将被截获代理人。
通过将事务模式更改为AOP解决了该问题,此link对于配置新的事务模式非常有用。