#java #multithreading #hibernate #jpa #sql-update
#java #многопоточность #гибернация #jpa #sql-обновление
Вопрос:
У меня есть очередь сообщений, которая выдает сообщения с некоторой информацией об обновлении поля сущности. Существует 10 потоков, которые обрабатывают сообщения из очереди.
Например
- 1-й поток обрабатывает сообщение, этот поток должен обновить поле A из моей сущности с идентификатором 123.
- 2-й поток обрабатывает другое сообщение, этот поток должен одновременно обновить поле B из моей сущности с идентификатором 123.
Иногда после обновлений база данных не содержит некоторых обновленных полей.
какой-то механизм обновления:
someService.updateEntityFieldA(entityId, newFieldValue);
какой-то сервис:
public Optional<Entity> findById(String entityId) {
return Optional.ofNullable(new DBWorker().findOne(Entity.class, entityId));
}
public void updateEntityFieldA(String entityId, String newFieldValue) {
findById(entityId).ifPresent(entity -> {
entity.setFieldA(newFieldValue);
new DBWorker().update(entity);
});
}
работник базы данных:
public <T> T findOne(final Class<T> type, Serializable entityId) {
T findObj;
try (Session session = HibernateUtil.openSessionPostgres()) {
findObj = session.get(type, entityId);
} catch (Exception e) {
throw new HibernateException("database error. " e.getMessage(), e);
}
return findObj;
}
public void update(Object entity) {
try (Session session = HibernateUtil.openSessionPostgres()) {
session.beginTransaction();
session.update(entity);
session.getTransaction().commit();
} catch (Exception e) {
throw new HibernateException("database error. " e.getMessage(), e);
}
}
HibernateUtil.openSessionPostgres() получает каждый раз новый сеанс из
sessionFactory.openSession()
Возможно ли выполнить такую логику без блокировок потоков / оптимистической блокировки и пессимистической блокировки?
Ответ №1:
Если вы используете sessionFactory.openSession()
для того, чтобы всегда открывать новый сеанс, при обновлении hibernate может терять информацию о грязных полях, которые ему необходимо обновить, поэтому возникают проблемы и обновляются все поля.
Установка hibernate.show_sql
свойства в true
покажет вам инструкции SQL UPDATE
, сгенерированные hibernate.
Попробуйте провести рефакторинг своего кода, чтобы в той же транзакции загрузить сущность и обновить поле. session.update
Не требуется, поскольку сущность управляется, при фиксации транзакции hibernate удалит изменения и выпустит обновление SQL.