【问题标题】:Grails using spring security in SecurityFiltersGrails 在 SecurityFilters 中使用 Spring Security
【发布时间】:2012-11-07 23:36:36
【问题描述】:

在生产服务器的 grails 应用程序中,我遇到了一些问题。 在 securityFilters 我正在注入 springSecurityService 并且在某些时候我会问类似

if(springSecurityService?.currentUser?.client){
...
}

但是系统会抛出错误

Error 500: Internal Server Error
Class
org.hibernate.LazyInitializationException
Message
could not initialize proxy - no Session
Trace
   Line | Method
->>  32 | doCall            in SecurityFilters$_closure1_closure2_closure4
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|    82 | doFilterInternal  in com.linkedin.grails.profiler.ProfilerFilter
|   190 | invoke . . . . .  in org.apache.jk.server.JkCoyoteHandler
|   291 | invoke            in org.apache.jk.common.HandlerRequest
|   776 | invoke . . . . .  in org.apache.jk.common.ChannelSocket
|   705 | processConnection in     ''
|   898 | runIt . . . . . . in org.apache.jk.common.ChannelSocket$SocketConnection
^   636 | run               in java.lang.Thread

第 32 行是我调用上述 if 语句的地方。你知道如何解决这个 LazyInitializationException 吗?我做错了什么?

注意:“client”是该用户所属的域类,但在Person的belongsTo参数中没有提及

谢谢。

【问题讨论】:

    标签: grails spring-security lazy-initialization


    【解决方案1】:

    该事件在控制器的 Hibernate 会话之外运行,因此当您加载用户时,它会立即断开连接,并且延迟加载的集合或多对一引用将无法解析。解决此问题的最简单方法是将用户加载调用包装在 withTransaction 块中 - 它使 Hibernate 会话始终保持打开状态:

    AnyDomainClass.withTransaction { status ->
       if (springSecurityService?.currentUser?.client) {
          ...
       }
    }
    

    【讨论】:

      【解决方案2】:

      要强制域对象在任何地方都正确工作,您可能需要使用惰性属性。我不知道你的对象是什么样的,但如果有任何类型的对象关系,你可以强迫它们不懒惰。就像这样:

      class Card {
        static hasMany = [cardProperties: CardProperty]
        static mapping = {
          cardProperties lazy: false
        }
      }
      

      为确保您确实有一些可用的会话,您可能需要创建一个事务服务。任何服务都可以,但要确保它不包含该行

      static transactional = false
      

      如果您将该服务注入过滤器,它将自动创建一个事务并能够获取惰性属性。但要小心!这将开始和完成一个事务。由于您在过滤器中使用它,因此任何页面加载都会多一个事务。

      另一种选择是将 sessionFactory bean 注入您的过滤器。然后,您可以使用纯 Hibernate 语法。就像这个:

      sessionFactory.getCurrentSession().beginTransaction();
      

      这不是一个好主意,我不建议这样做,但它可能对你有用。但是请注意,转发请求会导致 2 次交易打开和 2 次交易关闭(这是不好的)。在决定是否提交事务时,您必须非常小心。但是,如果您确定在应用的每个页面上都需要数据库连接 - 这可能对您有用/

      【讨论】:

        猜你喜欢
        • 2018-10-23
        • 2011-03-31
        • 2015-03-20
        • 2019-10-16
        • 2019-05-09
        • 2017-05-26
        • 2012-02-19
        • 2012-09-09
        • 1970-01-01
        相关资源
        最近更新 更多