4

我刚刚跳上了其他人编写的一个似乎效率低下的功能,但是我对 JPA 的了解并不是很好,无法找到一个不是 Hibernate 特定的可移植解决方案。

简而言之,在循环中调用以插入每个新实体的 Dao 方法执行“entityManager.merge(object);”。

JPA规范中没有定义将实体列表传递给Dao方法并进行批量/批量插入而不是为每个对象调用合并的方法吗?

另外,由于 Dao 方法是用“@Transactional”注释的,我想知道是否每个合并调用都发生在它自己的事务中......这对性能没有帮助。

任何想法?

4

2 回答 2

7

不,vanilla JPA 中没有批量插入操作。

是的,每个插入都将在其自己的事务中完成。@Transactional属性(没有限定符)表示传播级别REQUIRED(如果事务不存在,则创建事务)。假设你有:

public class Dao {
  @Transactional
  public void insert(SomeEntity entity) {
    ...
  }
}

你来做这件事:

public class Batch {
  private Dao dao;

  @Transactional
  public void insert(List<SomeEntity> entities) {
    for (SomeEntity entity : entities) {
      dao.insert(entity);
    }
  }

  public void setDao(Dao dao) {
    this.dao = dao;
  }
}

这样,整个插入组就被包装在一个事务中。如果您正在谈论大量插入,您可能希望将其拆分为 1000、10000 或任何作为足够大的未提交事务的组,这可能会使数据库资源匮乏,并且可能仅由于大小而失败。

注意: @Transactional是一个 Spring 注解。请参阅Spring 参考中的事务管理

于 2009-09-01T15:15:39.380 回答
0

如果你心情不好,你可以做的是:

@Entity
public class SomeEntityBatch {

    @Id
    @GeneratedValue
    private int batchID;
    @OneToMany(cascade = {PERSIST, MERGE})
    private List<SomeEntity> entities;

    public SomeEntityBatch(List<SomeEntity> entities) {
        this.entities = entities;
    }

}

List<SomeEntity> entitiesToPersist;
em.persist(new SomeEntityBatch(entitiesToPersist));
// remove the SomeEntityBatch object later

由于级联,这将导致实体被插入到单个操作中。

我怀疑这样做比简单地将单个对象保存在一个循环中是否有任何实际优势。查看 JPA 实现发出的 SQL 并进行基准测试会很有趣。

于 2012-06-26T17:14:05.717 回答