2012-11-07 48 views
0

在我的生產服務器的grails應用程序中,我遇到了一些問題。 在securityFilters我注入springSecurityService,在某些時候,我問類似在SecurityFilters中使用彈簧安全的Grails

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?我做錯了什麼?

注:「客戶端」是該用戶所屬,但它不是在人

致謝屬於關聯參數中提到的域類。

回答

0

要強制域對象處處正確的工作,你可能想使用延遲屬性。我不知道你的對象是什麼樣的,但是如果有任何形式的對象關係,你可能會強迫他們不懶惰。就像這樣:

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

爲確保您確實有一些會話可用,您可能需要創建一個事務服務。任何服務會做,但要確保它不包含線

static transactional = false 

如果注入的是服務,您的過濾器,它會自動創建一個交易,將能夠獲取延遲屬性。但要小心!這將開始並完成交易。由於您在過濾器中使用它,所以任何頁面加載都會有更多的事務。

另一種選擇是SessionFactory的bean的注入到過濾器。然後,你可以使用純粹的Hibernate語法。就像這樣:

sessionFactory.getCurrentSession().beginTransaction(); 

這不是一個好主意,我不會建議,但它可能適用於你。但是請注意,轉發請求導致2次交易開放和2次交易(這是不正常的)。在決定是否提交交易時,您必須非常小心。但是,如果你確定你需要你的應用程序的每個頁面上的數據庫連接 - 這可能爲你工作/

+0

這很有用,謝謝! – ufucuk

3

該事件的控制器的Hibernate會話外部運行,所以當你加載用戶立刻變得斷開和延遲加載的集合或多對一的引用將無法解析。解決這個問題的最簡單方法是將用戶負載調用包裝在withTransaction塊中 - 它使Hibernate會話始終保持打開狀態:

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