Hibernate完全以面向对象的方式来操作数据库当程序里以面向对象的方式操作持久化对象时将被自动转换为对数据库的操作例如我们调用Session的delete()方法来删除持久化对象Hibernate将负责删除对应的数据记录当我们执行持久化对象的setter方法时Hibernate将自动转换为底层的update语句修改数据库的对应记录
问题是如果我们需要同时更新条记录是不是要逐一加载条记录然后依次调用setter方法——这样不仅烦琐数据访问的性能也十分糟糕为了面对这种批量处理的场景Hibernate提供了批量处理的解决方案下面分别从批量插入批量更新和批量删除三个方面介绍如何面对这种批量处理的情形
批量插入
如果需要将条记录插入数据库通过Hibernate可能会采用如下做法
Session session = sessionFactoryopenSession();
Transaction tx = sessionbeginTransaction();
//循环次来插入条记录
for ( int i=; i<; i++ )
{
User u = new User ();
sessionsave(u);
}
mit();
sessionclose();
但随着这个程序的运行总会在某个时候运行失败并且抛出OutOfMemoryException(内存溢出异常)这是因为Hibernate的Session持有一个必选的一级缓存所有的User实例都将在Session级别的缓存区进行了缓存的缘故
为了解决这个问题有个非常简单的思路定时将Session缓存的数据刷入数据库而不是一直在Session级别缓存可以考虑设计一个累加器每保存一个User实例累加器增加根据累加器的值决定是否需要将Session缓存中的数据刷入数据库
下面是增加个User实例的代码片段
程序清单codes\\\batchInsert\src\lee\UserManagerjava
private void addUsers()throws Exception
{
//打开Session
Session session = HibernateUtilcurrentSession();
//开始事务
Transaction tx = sessionbeginTransaction();
//循环次插入条记录
for (int i = ; i < ; i++ )
{
//创建User实例
User u = new User();
usetName(xxxxx + i);
usetAge(i);
usetNationality(china);
//在Session级别缓存User实例
sessionsave(u);
//每当累加器是的倍数时将Session中数据刷入数据库
//并清空Session缓存
if (i % == )
{
sessionflush();
sessionclear();
}
}
//提交事务
mit();
//关闭事务
HibernateUtilcloseSession();
}
上面的代码中当i % == 时手动将Session处缓存的数据写入数据并且清空Session缓存里的数据除了要对Session级别缓存进行处理外还应该通过如下配置来关闭SessionFactory的二级缓存
hibernatecacheuse_second_level_cache false
注意除了要手动清空Session级别的缓存外最好关闭SessionFactory级别的二级缓存否则即使手动flush Session级别的缓存但因为在SessionFactory还有二级缓存也可能引发异常关于二级缓存的介绍请参考后面的内容