我们正在使用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语句。有没有办法让Hibernate在像INSERT INTO MyEntityMap () VALUES (), (), (), (), ()
这样的批量插入中插入值?
答案 0 :(得分:3)
我有完全相同的情况,这就是我最终做的......
在persistence.xml /等效文件
中使用以下配置<property name="hibernate.jdbc.batch_size" value="10"/>
<property name="hibernate.order_inserts" value="true"/>
<property name="hibernate.order_updates" value="true"/>
您给出的示例是批量插入,上面的配置只是将单个插入语句作为单个批处理发送到DB,它实际上并没有将插入重写为
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行)
引发的由于hibernate对重写一无所知,因此无法理解更新计数,我找不到合理的方法来挂钩我的Expectations类的实现......
这是一种死路,我们不能在hibernate中使用rewriteBatchedStatements功能!!
除非你愿意做一个邪恶的黑客攻击...只是将类复制粘贴到完全相同的包层次结构下的项目代码中这意味着hibernate会选择你的复制粘贴类而不是打包的类在hibernate jar中,然后只是注释掉if语句......并且是的,那么一切都顺利进行!!
小心考虑上述黑客;)