Исключение LazyInitializationException: не удалось инициализировать прокси — сервер-нет сеанса ленивого прокси, соединение с ложной выборкой?

#java #hibernate #hbm

Вопрос:

У меня есть случай, когда я получаю исключение LazyInitialzationException в своем проекте. Это происходит здесь:

     if (study.getIbId().equals(actor.getRepository().getIbId())) {
 

actor переменная — это тип Account и Repository есть тип Repository . Ibid Длинный тип. Учетная запись и репозиторий выходят из режима гибернации. Ошибка происходит из getIbId() , что означает Repository , что объект не был увлажнен(?). Вот Account.hbm.xml файл:

Учетная запись:

 ...
</many-to-one>
    <many-to-one cascade="all" class="com.accelarad.data.mapping.account.Repository" column="REPOSITORY_ID" lazy="proxy" name="repository" unique="true">
...
 

Как видите, lazy=proxy собственность есть. Когда я изменяю его на lazy=false , я больше не получаю исключение LazyInitializationException.

Из того, что я понимаю, если lazy=false, он охотно извлекается, поэтому это не эффективно. Есть ли способ сохранить lazy=proxy и загрузить Repository его ? Что значит lazy=${something} «и fetch=${something} «?

ИЗМЕНИТЬ: журнал ошибок:

 org.hibernate.LazyInitializationException: could not initialize proxy - no Session
    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:147)
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:260)
    at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:73)
    at com.accelarad.data.mapping.account.Repository_$_jvst9a5_5d.getIbId(Repository_$_jvst9a5_5d.java)
    at com.accelarad.smr.widgets.service.impl.ShareImageServiceImpl.isNetworkStudy(ShareImageServiceImpl.java:265)
    at com.accelarad.smr.widgets.ShareImageController.autoCompleteAccount(ShareImageController.java:231)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)

 

Комментарии:

1. не могли бы вы добавить журналы ошибок

2. Где вы открываете сессию?

Ответ №1:

Отсутствует некоторая информация, например, о том, как вы управляете сеансом и транзакциями. Исключение говорит вам только о том, что сеанс не привязан к вашему запросу.

Тем не менее я постараюсь указать вам хорошее направление. Сначала вам понадобится объект SessionFactory для управления вашими сеансами. Рекомендуется инкапсулировать его в одноэлементный шаблон, поскольку сеансы гибернации не являются потокобезопасными.

 public class HibernateFactory {

    private SessionFactory factory;
    private static HibernateFactory hf;

    private HibernateFactory() throws HibernateException {
        /* different versions of hibernate has different ways to build a session factory */
        factory = new Configuration().configure().buildSessionFactory();
    }
    
    /* synchronized so there is no multi use problems */
    synchronized public static HibernateFactory getInstance() throws HibernateException {
        if (hf == null) {
            hf = new HibernateFactory();
        }
        return hf;
    }

    /* will open a session and keep it open until closed manually */
    public Session getSession() throws HibernateException {
        return this.factory.openSession();
    }

    /* will open a session and close it automatically after transaction */
    public Session getCurrentSession() throws HibernateException {
        return this.factory.getCurrentSession();
    }

    public void finalize() throws HibernateException {
        this.factory.close();
    }
}
 

Итак, теперь вы можете вызвать сеанс hSession = HibernateFactory.getInstance().getSession();

Затем убедитесь, что ваша ленивая нагрузка находится внутри определенной вами транзакции.

 ...
Session session = HibernateFactory.getInstance().getSession();
session.beginTransaction();

if (study.getIbId().equals(actor.getRepository().getIbId())) {
...

session.getTransaction().commit()
session.close();
 

Как правило, вам не нужно будет явно открывать транзакцию, если вы просто извлекаете данные, но в любом случае это хорошая практика. Если вы это сделаете, не забудьте зафиксировать и откатить, если это необходимо.

Также для вашего другого вопроса о том, что такое извлечение и загрузка. См.: https://docs.jboss.org/hibernate/stable/core.old/reference/en/html/performance.html