如何使HQL生成SQL以在一个语句中插入多个值?

时间:2013-07-25 15:21:45

标签: mysql performance hibernate optimization hql

我需要hibernate来生成像这样INSERT INTO table_a (a_id, a_name) VALUES (5, 'a5'),(6, 'a6');的SQL。

使用这样的sql,你可以添加2行1个语句。我可以得到

a_id, a_name

------------------
5     a5
6     a6

当处于休眠状态时,当您保存一对多关系的集合时,hibernate将插入多个插入语句。这将导致如果您使用HQL将1000行插入到1个表中,将导致如下所示:

INSERT INTO scoring.table_a (`a_id`, `a_name`) VALUES (1, 'a');
INSERT INTO scoring.table_a (`a_id`, `a_name`) VALUES (2, 'a');
....
...
..
INSERT INTO scoring.table_a (`a_id`, `a_name`) VALUES (1000, 'a');

经过的时间是:

Executed 1,000 queries; elapsed time (seconds) - Total: 0.78, SQL query: 0.78, Building output: 0

当我使用相同的值进行测试时,使用SQL INSERT INTO table_a (a_id, a_name) VALUES (5, 'a'),(6, 'a'),(),...,...,(1000, 'a');将导致如下所示的经过时间:

Query 1 of 1, Rows read: 0, Elapsed time (seconds) - Total: 0.02, SQL query: 0.02, Building output: 0

我的测试结果是,1000个值(0.02s)的声明将比1000个插入语句快39倍,每个都有像hibernate那样的1个值(0.78s)。那么是否有一种方法可以使HQL生成类似于插入或可能更新的SQL。或者这意味着我们必须覆盖hibernate方言吗?

感谢任何提示

2 个答案:

答案 0 :(得分:0)

您可以将hibernate.jdbc.batch_size属性设置为非零值。它将允许Hibernate使用批处理INSERT。看看a official documentation

以下代码是如何通过Hibernate使用JDBC批量插入的示例:

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
for ( int i=0; i < 10000; i++ ) {
    RecordA record = new RecordA(.....);
    session.save(record);
    if ( i % BATCH_SIZE == 0 ) { // BATCH_SIZE is your choice, but equal to property
        //flush a batch of inserts and release memory:
        session.flush();
        session.clear();
    }
}
tx.commit();
session.close();

这里也讨论过:Hibernate batch size confusion

答案 1 :(得分:0)

HQL仅支持 INSERT INTO ......... SELECT ......... ;没有机会写 INSERT INTO ......... VALUES ,我的意思是在编写插入查询时,我们需要从其他表中选择值,我们不能手动插入我们自己的值。 (see documentationthis