Hibernate JPA更新多线程单个实体

问题描述

我有消息队列,该消息队列为消息提供了一些实体字段更新信息。有10个线程,用于处理队列中的消息。

例如

  • 一个线程处理消息,该线程应更新ID为123的我的实体中的字段A。
  • 第二个线程处理另一条消息,该线程应同时更新ID为123的我的实体中的字段B。

有时更新后数据库中不包含某些更新的字段。

一些更新程序:

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()

在没有线程锁定/乐观锁定和悲观锁定的情况下,这种逻辑是否可能?

解决方法

如果您使用sessionFactory.openSession()总是打开一个新会话,则在更新休眠状态下,可能会丢失有关它需要更新的脏字段的信息,因此会发布并更新所有字段。

hibernate.show_sql属性设置为true会向您显示由休眠生成的SQL UPDATE语句。

尝试重构代码,以在同一事务中加载实体并更新字段。不需要session.update,因为该实体是受管理的,因此在事务提交休眠时,休眠将刷新更改并发出SQL更新。