18hibernate hibernate的性能优化之session.clear()、1+N问题、list和iterate的区别

1.session.clear()
	注意session.clear()的运用,尤其在不断分页循环的时候
	a.比如:在一个大集合中进行遍历,遍历msg,取出其中的含有敏感字样的对象
		
		如果每次翻页都产生一个session,那之前的session就被清除了
		(实际上由java虚拟机的GC帮忙清除),不会产生问题;
		但如果一直在同一个session里不断读取,之前的数据因为存在引用,GC不会清除,
		那么会产生内存溢出。
		一般分页每个页面单独产生一个session,但如果是导数据和处理数据就会有这个问题。
	
	b.另外一种形式的内存泄露

	//面试题:java有内存泄露吗?
	语法级别上没有,实际上运用的时候会产生。
	因为不用回收内存,GC会自动回收。但如果用到了某些资源,一定要注意回收,
	比如打开了连接池的连接要记得关闭;比如打开了文件要记得关闭,
	否则就不能调用本地的资源把文件关闭,打开文件相当于调了C,C调了windows的API,
	C需要手动回收内存,那么就会产生java内存泄露。


2.1+N问题//典型面试题
	问题描述:
	public void testSave(){//类设计参考17hibernate
		Session session = sf.openSession();
		session.beginTransaction();

		for(int i=0;i<10;i++){
			Category c = new Category();
			c.setName("c"+i);
			Topic t = new Topic();
			t.setCategory(c);
			t.setTitle("t"+i);
			t.setCreateDate(new Date());
			session.save(c);
			session.save(t);
		}

		session.getTransaction().commit();
		session.close();
	}
	
	public void testQuery1(){
		Session session = sf.openSession();
		session.beginTransaction();

		List<Topic> topics = 
			(List<Topic>)session.createQuery("from Topic").list();
		for(Topic t:topics){
			System.out.println(t.getId()+"-"+t.getTitle());
		}	
		session.getTransaction().commit();
		session.close();
	}

	//1+N问题阐述(OneToMany或ManyToOne):
	Topic对Category是ManyToOne,fetchType设为eager时
	查询Topic时,查询语句如下:
	一条语句查询出所有符合条件的Topic,
	同时被关联的对象Category被取出的时候又发出N条sql语句
	所以一共是:一条语句查询Topic + N条语句查询Category

	解决方案:
	a.Lazy//此时N条语句在使用的时候才发出
	b.BatchSize//不是正规的解决方法,因为其他关联Category的类也会被限制
		在Category类上加注解 @BatchSize(size=5),
		即加载Category类的时候一次最多加载5条,
		此时发出的sql语句是N/5(N%5=0)或N/5+1(N%5!=0)条
	c.join fetch//Criteria默认使用join fetch,本质是外连接,只发出一条sql语句		
		List<Topic> topics = 
			(List<Topic>)session.createQuery("from Topic t left join fetch t.category c").list();


3.Query的list方法和iterate方法不同之处
	public void testQueryList(){
		Session session = sf.openSession();
		session.beginTransaction();

		List<Topic> topics = 
			(List<Topic>)session.createQuery("from Topic").list();
		for(Topic t:topics){
			System.out.println(t.getTitle());
		}	
		session.getTransaction().commit();
		session.close();
	}

	public void testQueryIterate(){
		Session session = sf.openSession();
		session.beginTransaction();

		Iterator<Topic> topics = 
			(Iterator<Topic>)session.createQuery("from Topic").iterate();
		//此处返回List<Topic>也可以,因为List实现了Iterator接口
		while(topics.hasNext()){			
			t = topics.next();
			System.out.println(t.getTitle());
		}	
		session.getTransaction().commit();
		session.close();
	}
	a.list取所有
	b.iterate先取ID,等用到的时候再根据ID来取对象
	c.session中list第二次发出,仍会到数据库查询
	d.iterate第二次,首先找session缓存

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值