#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
извлечения данных.
Вы можете прочитать больше о различных типах сеанса здесь:
Ответ №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 сеанса
второе: изменить поля
затем: делайте все, что вы хотите сделать