Hibernate - Избежание исключения LazyInitializationException - Отсоединение объекта от прокси и сеанса - PullRequest
5 голосов
/ 17 августа 2010
MyObject myObject = repositoryHibernateImpl.getMyObjectFromDatabase();
//transaction is finished, and no, there is not an option to reopen it
ThirdPartyUtility.doStuffWithMyObjectType( myObject );

на данный момент вы уже определили, что загружено лениво и нетерпеливо, и сторонняя утилита попытается вызвать все методы вашего экземпляра "myObject", это нормально, потому что вы не хотите ничего возвращать для лениво загруженных свойств, к сожалению, он не возвращает ноль, он выдает LazyInitializationException.

Это происходит потому, что вы на самом деле вызываете метод на прокси Hibernate вашего объекта, и он знает, что он не получил эти данные, и выдает исключение.

Можно ли даже получить базовый объект с нулевыми значениями, чтобы получатель просто возвращал ноль и не выбрасывал исключение? По сути, отсоединение объекта, чтобы Hibernate больше не осознавал его. Метод доступа к объекту, который загружается лениво, должен возвращать ноль, он не может возвращать фактические значения, мы хотим иметь возможность преобразовать сущность в POJO без необходимости создавать объект, который выглядит точно так же, как сущность и должен переназначить все значения.

Ответы [ 3 ]

2 голосов
/ 17 августа 2010

Допустим, у вас есть поле, в геттере вы можете:

MyField getMyField() {
    if (Hibernate.isInitialized(myField)) {
        return myField;
    }
    return null;
}

Из javadoc org.hibernate.Hibernate:

public static boolean isInitialized (Object proxy): проверить, если прокси или постоянная коллекция инициализируется.

0 голосов
/ 22 сентября 2017

проверьте мое решение.

Минимальный пример:

Я загружаю свойство не из объекта, а из контроллера.
Код:

{..}

MyProp prop = employeeController.getMyProp(employee);

{..}

Это инициализирует свойство через объект репозитория.и возвращает его.
EmployeeController.java:

public Set<MyProp> getMyProp(Employee employee) {

    if (this.employeeRepository.InitMyProp(employee)){

        return employee.getMyProp();
    }

    return null;
}

Репозиторий получить / открыть сеанс, перезагрузить объект сотрудника !и инициализировать загруженное ленивое поле
EmployeeRepository.java:

public boolean InitMyProp(Employee employee) {

    if (Hibernate.isInitialized(employee.getMyProp())){
        return true;
    }

    try {
        Session session = getSession();

        session.refresh(employee);

        Hibernate.initialize(employee.getMyProp());

    } catch (Exception ex) {
        return false;
    }

    return true;
}

private Session getSession(){

    if (session == null || !session.isConnected() || !session.isOpen()){
        session = HibernateUtil.getSessionFactory().getCurrentSession();
    }
    if (!session.getTransaction().isActive()) {
        session.beginTransaction();
    }
    return session;
}

В моем решении есть TableView с несколькими тысячами записей и еще 2 TableViews с подробностями выбранной записи в первом TableView.
надеюсь, это поможет.

0 голосов
/ 09 декабря 2011

Если вы не хотите связывать свой домен с Hibernate, другая возможность состоит в том, чтобы ваш DAO создавал собственный экземпляр объекта изнутри getMyObjectFromDatabase () и заполнял его соответствующими полями из прокси Hibernate. Я сделал это, и это работает хорошо.

Очевидно, что это больше кода, но вам гарантирован «чистый» экземпляр вашей сущности (с нулевыми неинициализированными значениями), если вы этого хотите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...