1

関数 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: No Session found for current thread」という例外が発生しました (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)
4

1 に答える 1

1

Groovy クラスでは、プロパティ アクセス

service.defects

は への呼び出しになりservice.getProperty("defects")、そのデフォルトの実装は最終的に に委譲されservice.getDefects()ます。そのスタック トレースを下から見ていくと、Spring AOP プロキシであるオブジェクトIncidentControllerが呼び出さgetProperty("incidents")れます。service

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実装はImportLogsService通常のデフォルトの動作を行い、独自のgetIncidentsメソッドを呼び出します

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)

これはターゲット サービス オブジェクトの内部にあるため、Spring トランザクション プロキシ レイヤーを再度通過しないことに注意してください。したがって、がトランザクション インターセプターgetIncidents()としてマークされていても、呼び出されません。@Transactional最後getIncidents()にDAOレイヤーを呼び出します

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)

コンテキストが設定されていないため失敗します。

最初に呼び出した場合service.getIncidents()、そのメソッド (トランザクションとしてマークされている) が Spring プロキシへの最初のエントリ ポイントとなり、トランザクション コンテキストが正しく設定されます。

個々のメソッドだけでなく、ImportLogsService クラス全体に として注釈を付けてみてください。@Transactionalこれにより、トランザクション インターセプタが起動するgetPropertyだけでなく、getIncidents().

于 2013-07-22T15:51:14.910 に答える