【问题标题】:Merge multiple objects with Hibernate使用 Hibernate 合并多个对象
【发布时间】:2021-10-07 10:12:06
【问题描述】:

我将 JPA 与 Hibernate 和 spring-boot-starter-data-jpa 一起使用。 我想合并/更新一组项目。如果它是一个新项目,我想保留,如果它是一个已经存在的项目,我想更新它。

    @PersistenceContext(unitName = "itemEntityManager")
    private EntityManager em;

    @Transactional
    public void saveItems(Set<Item>> items) {
        items.forEach(em::merge);
    }

当我这样尝试时,每个项目都会创建一个新的 HQL 语句并且它性能不佳。 所以我正在寻找一种方法来一次性保存所有项目(如果可能的话),以节省通话和时间。

我发现了这个:

        EntityTransaction transaction = em.getTransaction();
        transaction.begin();
        items.forEach(em::merge);
        transaction.commit();

但我不能使用此事务,因为我使用了 @Transactional。 有没有原生 SQL 的方法?

【问题讨论】:

  • 你到底想做什么?你确定要merge吗?这意味着“项目”包含 分离 实体,并且您希望将它们的状态带回持久性上下文中。 Hibernate 将需要每个尚未在缓存中的项目进行一个(或多个)查询,并且每个项目需要一个(或多个)更新。 (不过有一些方法可以提高性能,例如,语句批处理和在某些情况下休眠特定的update 方法)
  • 如果项目不存在,我想保存它,如果它已经存在则更新

标签: java hibernate jpa spring-data-jpa


【解决方案1】:

您可以为此使用@SQLInsert 来使用批量插入。见Hibernate Transactions and Concurrency Using attachDirty (saveOrUpdate)

【讨论】:

    【解决方案2】:

    我创建了一个原生 SQL 语句:

    1. 我将所有项目作为 sql 格式的值列表加入
    String sqlValues = String.join(",", items.stream().map(this::toSqlEntry).collect(Collectors.toSet()));
    
    1. 然后我调用了原生查询
        em.createNativeQuery("INSERT INTO config_item"
                    + "( id, eaid, name, type, road, offs, created, deleted )"
                    + " VALUES " + sqlValues
                    + " ON CONFLICT (id) DO UPDATE "
                    + " SET "
                        + "eaid=excluded.eaid,\n"
                        + "name=excluded.name,\n"
                        + "type=excluded.type,\n"
                        + "road=excluded.road,\n"
                        + "offs=excluded.offs,\n"
                        + "created=excluded.created,\n"
                        + "deleted=excluded.deleted;"
            ).executeUpdate();
    

    这样会快很多并且有效

    【讨论】:

      猜你喜欢
      • 2019-08-24
      • 2013-08-01
      • 2018-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-08
      • 2020-01-18
      • 1970-01-01
      相关资源
      最近更新 更多