hibernate学习笔记3 —— 批量更新 检索策略

批量更新:

1)session => jdbc-bache-size=?   10至50间为佳

<property name="jdbc.batch_size">20</property><!-- Hibernate的配置文件中设置JDBC单次批量处理的数目,合理的取值通常为10到50之间 -->


// 测试
		for (int i = 1; i <= 100; i++) {
			// 对象
			Depts depts = new Depts(new Long(i), "T" + i);
			// 保存
			session.save(depts);

			// 判断
			if (i % 20 == 0) {// 单次批量操作的数目为20
				session.flush(); // 清理缓存,执行批量插入20条记录的SQL insert语句
				session.clear(); // 清空缓存中的Depts对象
			}
		}

批量添加、更新、删除时需要适当的清理缓存。

首先需要关闭hibernate 二次缓存。


2)hql进行批量更新(HQL只支持insert into ... select ...形式的插入语句,而不支持"insert into ... values ... "形式的插入语句。)

String hql="update Dept set d.dname='IT'";

session.createQuery().executeUpdate();

String hql="insert into Depts(deptno,dname) select d.deptno,d.dname from Dept d";

3)jdbc来执行批量更新

// sql语句
		final String sql = "update Depts d set d.dname='IT'";
		
		//定义一个匿名类,实现了Work接口
		Work work=new Work() {
			
			@Override
			public void execute(Connection connection) throws SQLException {
				
				PreparedStatement ps = connection.prepareStatement(sql);
				
				ps.execute();
				
			}
		};
		
		//执行work
		session.doWork(work);

以上批量更新方式有两个缺点:
占用大量内存,必须把1万个Customer对象先加载到内存,然后一一更新它们。
执行的update语句的数目太多,每个update语句只能更新一个Customer对象,必须通过1万条update语句才能更新1万个Customer对象,频繁地访问数据库,会大大降低应用的性能。


一般说来,应该尽可能避免在应用层进行批量操作,而应该在数据库层直接进行批量操作,例如直接在数据库中执行用于批量更新或删除的SQL语句,如果批量操作的逻辑比较复杂,则可以通过直接在数据库中运行的存储过程来完成批量操作。
并不是所有的数据库系统都支持存储过程。例如目前的MySQL就不支持存储过程,因此不能通过存储过程来进行批量更新或批量删除。
当然,在应用层也可以进行批量操作,主要有以下方式:


(1)通过Session来进行批量操作。

      注意:

   (a)需要在Hibernate的配置文件中设置JDBC单次批量处理的数目,合理的取值通常为10到50之间,例如:hibernate.jdbc.batch_size=20

   (b)Hibernate的第二级缓存是关闭的,此外也可以在Hibernate的配置文件中通过如下方式显式关闭第二级缓存:hibernate.cache.use_second_level_cache=false



(3)通过HQL来进行批量操作。

  HQL(Hibernate Query Language,Hibernate查询语言)不仅可以检索数据,

  还可以用于进行批量更新、删除和插入数据。批量操作实际上直接在数据库中完成,所处理的数据不会被保存在Session的缓存中,因此不会占用内存空间。


(4)直接通过JDBC API来进行批量操作。

   当通过JDBC API来执行SQL insert、update和delete语句时,SQL语句中涉及到的数据不会被加载到内存中,因此不会占用内存空间。

以下程序直接通过JDBC API来执行用于批量更新的SQL语句:

值得注意的是,在Hibernate3中,尽管Session的connection()方法还存在,但是已经被废弃,不提倡使用了,

不过Hibernate3提供了替代方案:org.hibernate.jdbc.Work接口表示直接通过JDBC API来访问数据库的操作,

Work接口的execute()方法用于执行直接通过JDBC API来访问数据库的


HIbernate 检索策略:

检索策略                            运行机制

立即检索                           立即加载与当前对象并联的对象,需要执行多条select语句      n+1条语句

延迟检索                           不立即加载与当前对象关系关联的对象,在第一次访问关联对象时才加载其信息

迫切左外连接检索           通过左外连接加载与当前对象的关联对象为立即检索策略,但执行的select语句少,只执行1条select连接查询语句


查询:   lazy="true"   延迟查询

load()          仅影响session的load()方法

lazy 属性默认为true    即进行延迟加载。


延迟查询:在实际调用查询结果时检索

立即查询:在调用load/get时检索


Session get()  /  load()

检索策略包括:

1)类级别 lazy = "true"

对于Session的检索方式,类级别检索策略仅适用于load方法 ;也就说,对于get、qurey检索,持久化对象都会被立即加载而不管lazy是false还是true。

 一 般来说,我们检索对象就是要访问它,因此立即检索是通常的选择。由于load方法在检索不到对象时会抛出异常(立即检索的情况下),因此我个人并不建议使 用load检

索;而由于<class>中的lazy属性还影响到多对一及一对一的检索策略,因此使用load方法就更没必要了

2)关联级别 lazy="true"

有立即检索、延迟检索和迫切左外连接检索。

对于关联级别检索,又可分为一对多和多对多、多对一和一对一两种情况讨论。

 一对多和多对多关联关系一般使用<set>配置。<set>有lazy和outer-join属性,它们的不同取值绝对了检索策略。

1)立即检索:这是一对多默认的检索策略,此时lazy=false,outer-join=false.尽管这是默认的检索策略,但如果关联的集合是无用的,那么就不要使用这种检索方式。

2)延迟检索:此时lazy=true,outer-join=false(outer-join=true是无意义的),这是优先考虑的检索方式。

3)迫切左外连接检索:此时 lazy=false,outer-join=true,这种检索策略只适用于依靠id检索方式(load、get),而不适用于query的集合检索 (它会采用立即检索策略)。相

比于立即检索,这种检索策略减少了一条sql语句,但在Hibernate中,只能有一个<set>配置成 outer-join=true.

 多对一和一对一检索策略一般使用<many-to-one>、<one-to-one>配置。<many- to-one>中需要配置的属性是 outer-join,同时还需要配置one端关联的<class>的lazy属性

(配置的可不是<many-to-one>中 的lazy哦),它们的组合后的检索策略如下:

1) outer-join=auto:这是默认值,如果lazy=true为延迟检索,如果lazy=false为迫切左外连接检索。

2) outer-join=true,无关于lazy,都为迫切左外连接检索。

3) outer-join=false,如果lazy=true为延迟检索,否则为立即检索。

可以看到,在默认的情况下(outer-join=auto,lazy=false),对关联的one端对象Hibernate采用的迫切左外连接检索。 依我看,很多情况下,我们并不需要加载one端关联的

对象(很可能我们需要的仅仅是关联对象的id);另外,如果关联对象也采用了迫切左外连接检索,就会 出现select语句中有多个外连接表,如果个数多的话会影响检索性能,

这也是为什么Hibernate通过 hibernate.max_fetch_depth属性来控制外连接的深度。对于迫切左外连接检索,query的集合检索并不适用,它会采用立即检索策 略。

 对于检索策略,需要根据实际情况进行选择。对于立即检索和延迟检索,它们的优点在于select语句简单(每张表一条语句)、查询速度快,缺点在于关联表 时需要多条select

语句,增加了访问数据库的频率。因此在选择即检索和延迟检索时,可以考虑使用批量检索策略来减少select语句的数量(配置 batch-size属性)。对于切左外连接检索,优点

在于select较少,但缺点是select语句的复杂度提高,多表之间的关联会是很耗时的操作。 另外,配置文件是死的,但程序是活的,可以根据需要在程序里显示的指定检索策略

(可能经常需要在程序中显示指定迫切左外连接检索)。为了清楚检索策略的配 置效果如何,可以配置show_sql属性查看程序运行时Hibernate执行的sql语句。 

详细可查看:点击打开链接



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值