函数service.defects和service.getDefects()
的调用之间在groovy中有什么区别@RequestMapping("/test1")
ModelAndView getTest1() {
ModelAndView mav = new ModelAndView()
mav.viewName = "test"
List<Defect> defects = service.defects
mav
}
@RequestMapping("/test2")
ModelAndView getTest2() {
ModelAndView mav = new ModelAndView()
mav.viewName = "test"
List<Defect> defects = service.getDefects()
mav
}
我在这个问题上挣扎了很长一段时间,虽然我觉得这些电话都是一样的,但事实并非如此。在我的场景中,service.defects的调用导致了“org.hibernate.HibernateException:找不到当前线程的会话”异常(getDefects()虽然是Transactional)。
当我用“service.defects”调用方法时,有人可以解释一下我发生了什么吗
这是我得到的堆栈跟踪:
org.hibernate.HibernateException: No Session found for current thread
at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:97)
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:883)
at org.hibernate.SessionFactory$getCurrentSession.call(Unknown Source)
at com.test.dao.LogDBDao.getExceptionLogFileEntry(LogDBDao.groovy:35)
at com.test.dao.ILogDBDao$getExceptionLogFileEntry.call(Unknown Source)
at com.test.service.ImportLogsService.getIncidents(ImportLogsService.groovy:34)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
at groovy.lang.MetaClassImpl.getProperty(MetaClassImpl.java:1580)
at groovy.lang.MetaClassImpl.getProperty(MetaClassImpl.java:3308)
at com.test.service.ImportLogsService.getProperty(ImportLogsService.groovy)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:198)
at com.test.service.$Proxy27.getProperty(Unknown Source)
at org.codehaus.groovy.runtime.callsite.PogoGetPropertySite.getProperty(PogoGetPropertySite.java:47)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGetProperty(AbstractCallSite.java:227)
at com.test.controller.IncidentController.getIncidents(IncidentController.groovy:22)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
答案 0 :(得分:1)
在Groovy类中,属性访问
service.defects
成为对service.getProperty("defects")
的调用,其默认实现最终将委托给service.getDefects()
。因此,从IncidentController
调用getProperty("incidents")
调用service
对象(这是一个Spring AOP代理)来处理堆栈跟踪。
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:198)
at com.test.service.$Proxy27.getProperty(Unknown Source)
at org.codehaus.groovy.runtime.callsite.PogoGetPropertySite.getProperty(PogoGetPropertySite.java:47)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGetProperty(AbstractCallSite.java:227)
at com.test.controller.IncidentController.getIncidents(IncidentController.groovy:22)
该方法不标记为事务性,因此Spring在调用基础对象上的方法之前无需设置事务上下文
at com.test.service.ImportLogsService.getProperty(ImportLogsService.groovy)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
现在getProperty
的{{1}}实现执行常规默认行为并调用自己的ImportLogsService
方法
getIncidents
请注意,这是目标服务对象的内部,因此不再次通过Spring事务代理层。因此,即使at com.test.service.ImportLogsService.getIncidents(ImportLogsService.groovy:34)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
at groovy.lang.MetaClassImpl.getProperty(MetaClassImpl.java:1580)
at groovy.lang.MetaClassImpl.getProperty(MetaClassImpl.java:3308)
被标记为getIncidents()
,也不会调用事务拦截器。最后@Transactional
调用DAO图层
getIncidents()
失败,因为没有设置上下文。
如果您首先调用at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:97)
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:883)
at org.hibernate.SessionFactory$getCurrentSession.call(Unknown Source)
at com.test.dao.LogDBDao.getExceptionLogFileEntry(LogDBDao.groovy:35)
at com.test.dao.ILogDBDao$getExceptionLogFileEntry.call(Unknown Source)
,那么该方法(标记为事务性)将是进入Spring代理的第一个点,并且将正确设置事务上下文。
尝试将整个service.getIncidents()
类注释为ImportLogsService
,而不仅仅是单个方法。这会导致交易拦截器在@Transactional
以及getProperty
上触发。