我们使用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 (), (), (), (), ()
这样的批量插入中插入值?我有完全相同的场景,这就是我最终做的…
在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 . basicexpectations . verifyoutcome()方法抛出的(第67行)
由于hibernate对重写一无所知,它无法理解更新计数,我找不到一个合理的方法来挂钩我的期望类的实现…
这是一个死胡同,我们不能在hibernate中使用rewriteBatchedStatements特性!!
好吧,除非你愿意做一个邪恶的黑客,那就是…只需将类复制粘贴到你的项目代码中,在完全相同的包层次结构下,这意味着hibernate将选择复制粘贴的类,而不是打包在hibernate jar中的类,然后只需注释掉if语句…是的,然后一切都很顺利!!
仔细考虑上面的hack;)