【问题标题】:how to make HQL that will generate SQL to insert multiple values in one statement?如何制作将生成 SQL 以在一条语句中插入多个值的 HQL?
【发布时间】:2013-07-25 14:12:06
【问题描述】:

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

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

a_id, a_name

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

在hibernate中,当你保存一组一对多关系时,hibernate会插入multiple insert statement。如果您使用 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.02 秒)的 1 个语句将比 1000 个插入语句快 39 倍,每个语句都有 1 个值(0.78 秒),就像休眠一样。那么有没有一种方法可以让 HQL 生成类似用于插入或更新的 SQL。或者这意味着我们必须重写休眠方言?

感谢任何提示

【问题讨论】:

    标签: mysql performance hibernate optimization hql


    【解决方案1】:

    在 Hibernate 文档中有一个关于 batch processing 的非常好的章节。

    设置属性

    hibernate.jdbc.batch_size 20
    

    然后使用此代码

    Session session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction();
    
    for ( int i=0; i<100000; i++ ) {
        Customer customer = new Customer(.....);
        session.save(customer);
        if ( i % 20 == 0 ) { //20, same as the JDBC batch size
            //flush a batch of inserts and release memory:
            session.flush();
            session.clear();
        }
    }
    
    tx.commit();
    session.close();
    

    根据您的需要从上面的代码中更改customer 对象。

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

        您可以将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

        【讨论】:

        • 据我所知,batch_size 设置是一个内存优化问题,以最大限度地减少往返而不发生内存泄漏。 插入仍然在一个事务中的多个语句中。所以 batch_size 不是这里的解决方案。不过还是谢谢..
        • Hibernate batch size confusion 中所述,hibernate.jdbc.batch_size 允许使用 JDBC2 API 功能,该功能将 连续 INSERT 语句与 相同签名 (表& cols) 合并到一个具有多个 如果主键不是 GenerationType.Identity. 的语句中
        • 是的,连续的 INSERT 语句单个 INSERT 语句不同。正如我之前在评论中所说,插入仍然在一个事务中的多个语句中
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-01-20
        • 2012-10-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多