在同一事务中同时使用 EntityManager 和 Spring Repository 时是否存在性能问题?

Are there performance issues when using both an EntityManager and Spring Repository in the same transacation?

我有一个案例,我的 Foo 包含一个对象 Bar,如果那个 Bar 对象在 BarRepository 中不存在,我想坚持它首先然后继续保存 Foo 对象(在第一次创建 Foo 对象时不需要这样做,但由于某些原因需要在用新的 Bar 对象更新它时这样做)。

我想知道将 EntityManager(更新)和 Spring 存储库(检查是否存在)结合在一起时是否被认为是不良做法或任何重大性能问题.

这是我的特殊情况:

@Service
@AllArgsConstructor
public class FooService {

  private final FooRepository fooRepository;
  private final BarRepository barRepository;
  private final EntityManagerFactory entityManagerFactory;

  // works fine
  public Foo update(long id, Consumer<Foo> consumer) {
    var foo = get(id);
    updateFields(foo, consumer);
    var entityManager = entityManagerFactory.createEntityManager();
    var transaction = entityManager.getTransaction();
    transaction.begin();
    if (foo.getBar() != null) {
      if (!barRepository.existsById(foo.getBar().getId())) {// option 1
        entityManager.persist(foo.getBar());
      }
    }
    var update = entityManager.merge(foo);
    transaction.commit();
    entityManager.close();
    return update;
  }

  // doesnt work yet, but the idea is this
  public Foo update(long id, Consumer<Foo> consumer) {
    var foo = get(id);
    updateFields(foo, consumer);
    var entityManager = entityManagerFactory.createEntityManager();
    var transaction = entityManager.getTransaction();
    transaction.begin();
    if (foo.getBar() != null) {
      var barId = foo.getBar().getId();
      if (entityManager // option 2
              .createNativeQuery(
                      "SELECT b FROM bar b WHERE b.text = ?1 AND b.duration = ?2")
              .setParameter(1, barId.getText()())
              .setParameter(2, barId.getDuration())
              .getSingleResult()
              == null) {
        entityManager.persist(foo.getBar());
      }
    }
    var update = entityManager.merge(foo);
    transaction.commit();
    entityManager.close();
    return update;
  }

}

在这两种方法中,第一种对我来说更清晰,因为 Foo 实体的检查是一个小的,与另一个相比,一个衬里,但我想遵循任何标准。

Spring Data JPA 构建于 JPA 之上并在内部使用 EntityManager。 Spring 数据从未旨在从您的代码库中完全删除 JPA。它的目标是让简单的东西变得简单和舒适,同时在您需要直接使用它时不会妨碍您。

因此,使用 EntityManager 完全没问题,而且对于许多非平凡的应用程序来说实际上是意料之中的。

但是访问 EntityManager 的代码与使用存储库的代码存在于不同的抽象层上。 因此,我建议将您的 EntityManager 使用代码移动到 custom methods of your repositories.