2012-02-28 69 views
0

我試圖使用休眠來建立一個本地緩存的數據,我從源網站拉。我擁有使用JPA配置的對象(如果它有所不同),並且可以在測試應用程序中正確讀/寫它們。使用Hibernate獲取通用對象

現在我想將代碼移入一個通用的「緩存」類,以便我可以從緩存中請求一個對象並按正常方式處理該對象。我可以從數據庫讀取對象並將其傳回給調用類,但是當我嘗試訪問對象中的集合時,我會遇到可怕的延遲初始化異常。 我知道是什麼導致了這種情況,我從中讀取對象的類從數據庫中讀取對象之後並在將對象返回給調用類之前提交該事務。

我已經嘗試過各種方法來解決這個問題,最簡單的(對我來說)似乎是嘗試訪問對象中的所有集合,以確保它們在關閉事務並返回對象之前加載。

該方法的問題是,我不知道我從數據庫中檢索的對象的結構(Hibernate對我有利的一部分),因此我無法調用相應的方法來加載數據。我如何克服這一點?我並不想真正地抓取對象,因爲它們可能會被其他應用程序使用。我不想使用HBM文件,如果我可以避免它。

這是調用緩存類:

Series series = (Series) Cache.getFromCache(id, Series.class) 

在Cache類:

public static Object getFromCache(String key, Class clazz) { 
Object dbObject = HibernateUtil.loadObject(clazz, key); 

    if (dbObject != null) { 
     logger.debug("Cache (Get): Got object (" + clazz.getSimpleName() + ") for " + key); 
     return dbObject; 
    } 
} 

而且HibernateUtil的作用:

public static Object loadObject(Class clazz, Serializable key) { 
    Session session = sessionFactory.getCurrentSession(); 
    Object dbObject; 

    try { 
     session.beginTransaction(); 
     dbObject = clazz.cast(session.get(clazz, key)); 
    } finally { 
     session.getTransaction().commit(); 
    } 

    return dbObject; 

回答

1

首先,你能避免一種通過使您的loadObject方法參數化來投射的類型:

public static <T> T loadObject(Class<T> clazz, Serializable key) { 
    Session session = sessionFactory.getCurrentSession(); 
    T dbObject; 

    try { 
     session.beginTransaction(); 
     dbObject = clazz.cast(session.get(clazz, key)); 
    } 
    finally { 
     session.getTransaction().commit(); 
    } 

    return dbObject; 
} 

第二:你爲什麼用這種方法打開並提交事務?讓調用者打開一個事務並在完成使用它從緩存加載的對象時提交它將解決問題。

第三:如果您確實想讓此方法打開並關閉事務,則以Initializer<T>實例爲參數。這個初始化器有責任在返回實體之前初始化所有必要的關聯。

public static <T> T loadObject(Class<T> clazz, 
           Serializable key, 
           Initializer<T> initializer) { 
    Session session = sessionFactory.getCurrentSession(); 
    T dbObject; 

    try { 
     session.beginTransaction(); 
     dbObject = clazz.cast(session.get(clazz, key)); 
     initializer.initialize(dbObject); 
    } 
    finally { 
     session.getTransaction().commit(); 
    } 

    return dbObject; 
} 
+0

**第一:**非常感謝,我會更新。 **其次:**我試圖保持緩存代碼自包含,因爲它已被添加到一個現有的項目,我想一次重構項目的一部分,而不是一次完成。 **第三:**原諒我的無知,但什麼是初始化程序? – Omertron 2012-02-28 14:52:44

+0

初始化程序是一個您要創建的接口,它將包含一個'initialize(T)'方法,並且在從loadObject方法返回之前負責初始化T實體的關聯。 – 2012-02-28 14:57:15

+0

因此,它可能是一個工具類,例如只調用「.getCollection()。size」? 或者'initialize'屬於正在加載的類? – Omertron 2012-02-28 15:08:12