2016-09-24 32 views
1

当通过“数据提供者”进行流式处理时,我需要在数据库中插入相当多的实体,例如大约100.000。这整个步骤需要是事务性的。
为了简化我的用例,尽可能让我们假设这是我的代码:插入大量行而不将实体附加到持久性上下文

@Transactional 
public void execute() { 
    for (int i = 0; i < 100000; i++) { 
     carRespository.save(new Car()); 
    } 
} 

这段代码的问题是,即使很清楚我有没有用在汽车实体后插入查询生成的实体附加到持久性上下文并保存在内存中,直到事务完成。
我想确保在垃圾收集被触发的情况下,创建的实体被清除。对于这个目前我看到了两个解决方案:

  • 在存储库中创建一个本地插入查询
  • 注入EntityManager在服务和呼叫后,每em.detach(car)插入

我倾向于选择第二个选项因为我不需要在实体更改时管理本机插入语句。

你能确认我采取了正确的做法还是建议一个更好的选择。

回答

2

您可以在Hibernate documentation找到插入批处理数据的方法。

当为了控制第一级缓存的大小而定期创建新的对象持久刷新()然后清除()会话时。

因此,下面的方法建议:

Session session = sessionFactory.openSession(); 
Transaction tx = session.beginTransaction(); 

for (int i=0; i<100000; i++) { 
    session.save(new Car()); 
    if (i%20 == 0) { 
     session.flush(); 
     session.clear(); 
    } 
} 

tx.commit(); 
session.close(); 
+0

这将是实施的“纯”休眠方式我第二个建议(带分离的一个)。我承认你的建议是“偶尔一次”清除实体。我也可以用'em.clear()'来实现这一点。 – mvlupan

0

您可以尝试使用saveAndFlush(S entity)方法从春天数据JPA JpaRepository而不是save()

+0

从我的理解,这将冲刷到现场的数据库插入。我对该部分没有任何问题:从我的角度来看,这可以是单个插入或批量插入。我感兴趣的是确保实体可用于gc的最佳方式是什么。 – mvlupan

相关问题