【问题标题】:Hibernate JPA update multi threads single entityHibernate JPA 更新多线程单实体
【发布时间】:2020-08-18 17:17:50
【问题描述】:

我有消息队列,它提供带有一些实体字段更新信息的消息。有 10 个线程,处理来自队列的消息。

例如

  • 第一个线程处理消息,该线程应该更新我的实体中的字段 A,ID 为 123。
  • 第二个线程处理另一条消息,该线程应同时更新我的​​实体 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()

没有线程锁/乐观锁和悲观锁可以做这样的逻辑吗?

【问题讨论】:

    标签: java multithreading hibernate jpa sql-update


    【解决方案1】:

    如果您使用sessionFactory.openSession() 始终打开一个新会话,则在更新时休眠可能会丢失有关它需要更新的脏字段的信息,因此问题并更新到所有字段。

    hibernate.show_sql 属性设置为true 将显示由hibernate 生成的SQL UPDATE 语句。

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

    【讨论】:

      猜你喜欢
      • 2021-09-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-10
      • 1970-01-01
      • 2018-08-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多