2012-02-28 56 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