Возможно ли отсоединить объект Hibernate, чтобы изменения объекта автоматически не сохранялись в базе данных?

#java #hibernate #persistence

#java #переход в спящий режим #постоянство

Вопрос:

У меня есть объект Hibernate, который я должен преобразовать в JSON, и я должен перевести некоторые значения в entity, но когда я перевожу значения, эти значения мгновенно сохраняются в базе данных, но я не хочу сохранять эти изменения в базе данных. Есть ли какой-либо обходной путь для этой проблемы?

Ответ №1:

Вы можете отсоединить объект, вызвав Session.evict() .

Другие варианты — создать защитную копию вашего объекта перед переводом значений или использовать DTO вместо объекта в этом коде. Я думаю, что эти параметры более элегантны, поскольку они не связывают преобразование в JSON и уровень сохраняемости.

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

1. В случае JPA вы можете использовать: EntityManager.detach(object)

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

Ответ №2:

Я также конвертирую объекты hibernate в JSON.

Плохо то, что при закрытии сеанса вы не можете лениво загружать объекты. По этой причине вы можете использовать

 hSession.setDefaultReadOnly(true);
  

и закройте сеанс после того, как вы закончите с JSON.

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

1. Этот вариант следует признать лучшим ответом, поскольку он выполняет только минимум для решения проблемы, не затрагивая весь сеанс. Чтобы сделать ответ еще более конкретным: hSession.setReadOnly(myObject, true);

Ответ №3:

Вы также можете избежать привязки ваших объектов к сеансу гибернации, используя StatelessSession :

 StatelessSession session = sessionFactory.openStatelessSession();
  

вместо

 Session session = sessionFactory.getCurrentSession();
  

Обратите внимание, что вы должны самостоятельно позаботиться о закрытии StatelessSession , в отличие от обычного сеанса Hibernate:

 session.close(); // do this after you are done with the session
  

Другое отличие по сравнению с обычным сеансом заключается в том, что StatelessSession не может извлекать коллекции. Я вижу, что это основное назначение только для SQLQuery извлечения данных.

Вы можете прочитать больше о различных типах сеанса здесь:

http://www.interviewadda.com/difference-between-getcurrentsession-opensession-and-openstatelesssession/

Ответ №4:

Закройте сеанс. Это отсоединит ваш объект за вас, и никакие изменения не будут сброшены. Если это невозможно, посмотрите на отключение автозапуска … но это совсем другая проблема с червями. Проще всего закрыть сеанс и покончить с этим!

Ответ №5:

В моем случае я просто сбросил и очистил сеанс.

сеанс.flush(); session.clear();

Ответ №6:

 public static <E> E deepClone(E e) {
    ByteArrayOutputStream bo = new ByteArrayOutputStream();
    ObjectOutputStream oo;
    try {
        oo = new ObjectOutputStream(bo);
        oo.writeObject(e);
    } catch (IOException ex) {
        ex.printStackTrace();
    }
    ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
    ObjectInputStream oi;
    try {
        oi = new ObjectInputStream(bi);
        return (E) (oi.readObject());
    } catch (IOException ex) {
        ex.printStackTrace();
        return null;
    } catch (ClassNotFoundException ex) {
        ex.printStackTrace();
        return null;
    }
}
  

первое: глубокое копирование pojo сеанса

второе: изменить поля

затем: делайте все, что вы хотите сделать