Использование Hibernate для получения универсального объекта - PullRequest
0 голосов
/ 28 февраля 2012

Я пытаюсь использовать hibernate для создания локального кэша данных, которые я получаю с исходных веб-сайтов.У меня есть объекты, сконфигурированные с помощью JPA (если это имеет значение), и я могу нормально читать / записывать их в тестовом приложении.

Теперь я хочу переместить код в общий класс "Caching", чтобы я могможет запросить объект из кэша и обработать его как обычно.Я могу прочитать объект из базы данных и передать его обратно вызывающему классу, но когда я пытаюсь получить доступ к коллекциям в объекте, я получаю страшное исключение ленивой инициализации.Я знаю, что вызывает это, класс, из которого я читаю объект, фиксирует транзакцию после того, как он прочитал объект из базы данных и до того, как он возвращает объект в вызывающий класс.

Я пробовал различные методы, чтобы обойти этоэто, и самое простое (для меня), кажется, попытаться получить доступ ко всем коллекциям в объекте, чтобы убедиться, что они загружены перед закрытием транзакции и возвратом объекта.

Проблема с этим подходом заключается в том, чтоЯ не знаю структуру объекта, который я извлекаю из базы данных (для меня это часть преимущества Hibernate), и поэтому я не могу вызвать соответствующие методы для загрузки данных.Как мне это преодолеть?Я действительно не хочу делать нетерпеливую выборку объектов, поскольку они могут использоваться другими приложениями.Я не хочу использовать hbm-файлы, если могу избежать этого.

Это вызов класса Cache:

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 Ответ

1 голос
/ 28 февраля 2012

Прежде всего, вы можете избежать приведения типа, задав параметризованный метод 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...