我刚刚跳过了其他人写的功能,这个功能看起来效率不高,但是我对JPA的了解并不是很好找到一个不是特定于Hibernate的可移植解决方案。
简而言之,在一个循环中调用的Dao方法插入每个新实体都会执行“entityManager.merge(object);”。
是不是在JPA规范中定义了一种方法来将实体列表传递给Dao方法并执行批量/批量插入而不是为每个对象调用merge?
另外,由于Dao方法带有“@Transactional”注释,我想知道每个合并调用是否在自己的事务中发生......这对性能没有帮助。
有什么想法吗?
答案 0 :(得分: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 Reference中的Transactional Management。
答案 1 :(得分: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以及基准测试将会很有趣。