2

我们使用 Hibernate 4.2 作为 JPA 2.0 实体的支持库。我们有一个如下实体:

@Entity
public class MyEntity {
    ....
    @ElementCollection
    @MapKeyColumn(name = "key")
    @Column(name = "value")
    @CollectionTable("MyEntityMap")
    private Map<String, Integer> theMap;
    ...
}

该地图可能有数千个条目。我已经设置hibernate.jdbc.batch_size=50了,但是当我说entityManager.persist(myEntity). 有没有办法让 Hibernate 在批量插入中插入值INSERT INTO MyEntityMap () VALUES (), (), (), (), ()

4

1 回答 1

4

我有完全相同的场景,这就是我最终做的......

在 persistence.xml/equivalent 文件中使用以下配置

<property name="hibernate.jdbc.batch_size" value="10"/> 
<property name="hibernate.order_inserts" value="true"/> 
<property name="hibernate.order_updates" value="true"/>

您给出的示例是批量插入,上面的配置只是将单个插入语句作为单个批次发送到数据库,它实际上并没有将插入重写为

INSERT INTO MyEntityMap () VALUES (), (), (), (), ()

诚然,批量插入只提供了轻微的性能改进,真正的性能改进可以来自批量插入。

批量插入不是 ANSI SQL 功能,而是单个数据库提供程序的功能,MySQL DB 连接器驱动程序提供了将批量插入重写为批量插入的配置

要启用它,请使用如下连接字符串

jdbc.url=jdbc:mysql://localhost:3306/macula?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8&rewriteBatchedStatements=true

现在,一旦你完成了这个,如果你尝试运行应用程序,并在 mysql 中启用常规查询日志记录,你会看到你的插入被重写为批量插入......但你也会得到一个BatchedTooManyRowsAffectedException :)

这是由org.hibernate.jdbc.Expectations.BasicExpectation.verifyOutcome()方法抛出的(第 67 行)

由于休眠对重写一无所知,它无法理解更新计数,我找不到一种合理的方法来挂钩我的 Expectations 类的实现......

这是一种死胡同,我们不能在休眠中使用 rewriteBatchedStatements 功能!

好吧,除非你愿意做一个邪恶的黑客攻击......只需将类复制粘贴到完全相同的包层次结构下的项目代码中,这意味着 hibernate 将选择你复制粘贴的类,而不是打包在 hibernate jar 中的类,然后只需注释掉 if 语句......是的,然后一切顺利!

仔细考虑上面的黑客;)

于 2014-03-04T06:03:48.267 回答