Hibernate完全以面向对象的方式来操作数据库,当程序里以面向对象的方式操作持久化对象,将被自动转换为对数据库的操作。但存在这样一个问题,如果我们想同时更新100000条记录,是不是要逐一加载100000条记录,然后依次调用setter方法。采用这种方法实在是太繁琐了,而且严重影响了数据的访问性能。Hibernate提供的批量处理的方案来解决这个问题。
一、批量插入
如果我们需要插入100000条记录,通过hibernate可能会采用如下的方式处理:
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
for (int i = 0; i < 100000; i++) {
User user = new User();
user.setName("userName"+i);
user.setAge(i);
session.save(session);
}
tx.commit();
session.close();
但是这个程序存在一个问题:当程序运行到某个地方,总是会抛出OutOfMemoryException内存溢出异常。这是因为Hibernate的Session持有一个必选的一级缓存,所有的User实例都会Session级别的缓存区进行缓存的缘故。
如果你要执行批量处理并且想要达到一个理想的性能,那么使用JDBC的批量(batching)功能是至关重要。将JDBC的批量抓取数量(batchsize)参数设置到一个合适值。
<property name="jdbc.batch_size">20</property>
可能也会想到关闭二级缓存:
hibernate.cache.use_second_level_cache false
但这个并不是必须的。
解决这个问题的方案就是:定时的将session的缓存数据刷入数据库,同时通过调用clear()来控制一级缓存的大小。如下:
static void addUser() throws Exception{
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
//循环1000次,插入1000条记录
for(int i = 0;i < 100000;i++){
//创建User对象
User user = new User();
user.setName("userName"+i);
user.setAge(i);
//在session级别缓存User实例
session.save(user);
//每当累加器是20的倍数的时候,将session中数据刷入数据库,并且情况session缓存
if(i%20==0){
session.flush();
session.clear();
}
}
二、批量更新
上面介绍的方法同样也适用于批量更新。在进行会返回很多行数据的查询时,你需要使用scroll()方法以便充分利用服务器端游标所带来的好处。
static void updateUser() throws Exception {
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
//查询出User表中所有的记录
ScrollableResults re = session.createQuery("from User").setCacheMode(CacheMode.IGNORE).scroll(ScrollMode.FORWARD_ONLY);
int count = 1;
while(re.next()){
User user = (User) re.get(0);
//当count=20的倍数时,将更新的结果从session中flush到数据库
user.setName("新用户:"+count);
if(++count%20==0){
session.flush();
session.clear();
}
}
tx.commit();
session.close();
}
通过这种方式,虽然可以进行批量更新,但由于它需要先执行数据查询,然后才能执行数据更新,所以执行效率不高。为了避免这种情况,我们可以使用DML风格进行数据的批量更新。
三、DML风格的批量更新/删除
Hibernate提供通过Hibernate查询语言(HQL)来执行大批量SQL风格的DML语句的方法。
批量update、delete语句的语法格式如下:(UPDATE|DELETE)FROM?EntityName(WHEREwhere_conditions)。
这里需要注意如下几点:
1、在FROM子句中,FROM关键字是可选的。
2、在FROM子句(from-clause)中只能有一个实体名,它可以是别名。如果实体名是别名,那么任何被引用的属性都必须加上此别名的前缀;如果不是别名,那么任何有前缀的属性引用都是非法的。
3、不能在批量HQL语句中使用连接,显式或者隐式的都不行。不过在WHERE子句中可以使用子查询。可以在where子句中使用子查询,子查询本身可以包含join。
4、整个WHERE子句是可选的。
实例:使用Query.executeUpdate()方法执行一个HQLUPDATE语句
static void updateUser() throws Exception{
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
//定义批量更新的HQL语句
String hql = "update User as user set user.name = :name";
//执行更新
session.createQuery(hql).setString("name", "name").executeUpdate();
tx.commit();
session.close();
}
使用这种批量更新语法时,通常只需要执行一次SQL的update语句,就可以完成所有满足条件记录的更新。但也有可能需要执行多条update语句,这是因为有继承映射等情况。
执行一个HQLDELETE,同样使用Query.executeUpdate()方法:
//使用DML风格的批量删除
static void deleteUser() throws Exception{
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
//定义批量更新的HQL语句
String hql = "delete User";
//执行删除
session.createQuery(hql).executeUpdate();
tx.commit();
session.close();
}
Query.executeUpdate()方法返回一个整型值,该值是受此操作影响的记录数量。
分享到:
相关推荐
hibernate-commons-annotations-4.0.1.Final.jar hibernate-core-4.1.12.Final.jar hibernate-ehcache-4.1.12.Final.jar hibernate-entitymanager-4.1.12.Final.jar hibernate-jpa-2.0-api-1.0.1.Final.jar ...
赠送jar包:hibernate-jpa-2.1-api-1.0.2.Final.jar; 赠送原API文档:hibernate-jpa-2.1-api-1.0.2.Final-javadoc.jar; 赠送源代码:hibernate-jpa-2.1-api-1.0.2.Final-sources.jar; 赠送Maven依赖信息文件:...
赠送jar包:hibernate-jpa-2.1-api-1.0.2.Final.jar; 赠送原API文档:hibernate-jpa-2.1-api-1.0.2.Final-javadoc.jar; 赠送源代码:hibernate-jpa-2.1-api-1.0.2.Final-sources.jar; 赠送Maven依赖信息文件:...
hibernate-jpa-2.1-api-1.0.0.final-sources.jar 源码 hibernate-jpa-2.1-api-1.0.0.final-sources.jar 源码
很多人为了配置jpa找这个动态产生字节码的jar文件,hibernate-distribution-3.3.1.GA包太大,而hibernate-distribution-3.3.2.GA的jar没有这个jar文件,希望对大家有用
hibernate-annotations-3.4.0.GA hibernate-annotations-3.4.0.GA hibernate-annotations-3.4.0.GA
hibernate-jpa-2.0-api-1.0.1.Final.jar
hibernate-commons-annotations-5.0.1.Final.jar的源码
hibernate-jpa-2.1-api-1.0.0.final.jar.zip,内含hibernate-jpa-2.1-api-1.0.0.final.jar
hibernate-release-4.0.0.Final.zip
hibernate-release-4.3.10.Final.zip 官方原版,因上传文件大小限制,去掉里面的project
使用hibernate-validator 进行校验的jar包,里面包括了基础hibernate-validator-5.0.0.CR2.jar hibernate-validator-annotation-processor-5.0.0.CR2.jar 之外,还包括了el-api-2.2.jar javax.el-2.2.4等项目必不可...
hibernate-release-5.3.7.Final
flex3读书笔记----flex整合hibernate
hibernate-commons-annotations-4.0.1.Final.jar
hibernate-release-5.1.0.Final
hibernate-release-5.0.7.Final压缩包 -document -lib -project 内部Hibernate依赖库: antlr-2.7.7.jar dom4j-1.6.1.jar geronimo-jta_1.1_spec-1.1.1.jar hibernate-commons-annotations-5.0.1.Final.jar ...
hibernate-jpa-2.1-api-1.0.0.Final.jar官方下载,请放心使用
hibernate-configuration-3.0.dtd、hibernate-mapping-3.0.dtd、hibernate.properties(5.0.7)
Hibernate稳定版(hibernate-release-5.3.23.Final.zip),Hibernate ORM 是一个为应用程序、库和框架提供对象/关系映射 (ORM) 支持的库。它还提供了 JPA 规范的实现,这是 ORM 的标准 Java 规范。