如何在单个语句中插入所有行

时间:2013-10-04 07:03:34

标签: hibernate hql hibernate-criteria

如何在单个语句中插入所有行。这是我的代码,但插入行需要很长时间。

for(Myobject object : objectList)
        getCurrentSession().save(object);

它为每条记录创建一个语句;

insert into myobject (id, type) values (?, ?)
insert into myobject (id, type) values (?, ?)
....

我想做的是;

insert into myobject (id, type) values (?, ?), (?, ?), (?, ?) ......(?, ?);

有没有办法创建这个声明?

4 个答案:

答案 0 :(得分:3)

您可能对batch inserts on Hibernate tutorial感兴趣。

问题不在于save()操作,因为所有正在执行此操作的是将对象保存在第一级缓存中(在会话中,使其持久化),但是flush()触发插入的操作。他们建议采用以下方法,以实现良好的性能

在教程中也有人说 - 我还没有尝试过 - 你可以获得OutOfMemoryException非常多的持久性行,他们似乎建议20作为批量大小。< / p>

在使新对象持久化flush()然后清除()会话时,为了控制第一级缓存的大小。

for ( int i=0; i<objectList.size(); i++ ) {
   getCurrentSession().save(objectList.get(i));
   if ( i % 20 == 0 ) { //20, same as the JDBC batch size
    //flush a batch of inserts and release memory:
   session.flush();
   session.clear();
   }
}

编辑如果需要,还可以将配置文件中的hibernate.jdbc.batch_size设置为20.或50。 Hibernate必须对它们进行分组,而不是20个插入,你应该只有一个按20分组:

into myobject (id, type) values (id1, val1), (id2, val2), ......(id20, val20)

答案 1 :(得分:1)

我想添加一种设法使用"status": "ACTIVE", accountProfileId: "Premium", "accountNumber": "123", "billingAddress": [ { "key": "Children", "value": "y" } 解决此问题的方法。我从@Bohemian答案中获得了一些启发。首先,在 Service 层上,将对象列表分成多个块,然后在 DAO 层上,插入每个块。

服务

Native Queries

DAO

@Override
public void massInsert(List<Object> objects) throws Exception {

    // First, let's split the list in chunks.
    final int chunkSize = 50;
    final AtomicInteger counter = new AtomicInteger();
    final Collection<List<Object>> result =
            objects.stream().collect(Collectors.groupingBy(it -> counter.getAndIncrement() / chunkSize)).values();

    // Now, for each iteration, we will insert the corresponding details.
    for (List<Objects> oList : result) {
        this.dao.massInsert(oList);
    }
}

它的工作比逐行插入每一行要快得多。希望对您有所帮助。

答案 2 :(得分:0)

使用本机查询(原始SQL):

entityManager
  .createNativeQuery("insert into myobject (id, type) values (?, ?), (?, ?), (?, ?) ......(?, ?)")
  .setParameter(1, foo)
  // etc
  .execute();

答案 3 :(得分:0)

只需为hibernate启用&#34; DEBUG&#34;级别日志记录,并查看批量插入是否正在发生。

  log4j.rootLogger=TRACE, file, stdout

  log4j.logger.org.hibernate=TRACE

  log4j.logger.org.hibernate.type=ALL

你应该看到如下的日志。

  DEBUG AbstractBatcher:66 - Executing batch size: 20

在调用ps.executeBatch()之前,很快就会生成插入语句。 org.hibernate.jdbc.BatchingBatcher的第70行。