本文主要包括以下内容

性能优化的方法

发出的sql语句越少,性能越高
方法:
1、懒加载
2、抓取策略
3、缓存策略
4、HQL语句

懒加载

  • 类的懒加载
    1、利用session.load方法可以产生代理对象
    2、在session.load方法执行的时候并不发出sql语句
    3、在得到其一般属性的时候发出sql语句
    4、只针对一般属性有效,针对标示符属性是无效的
    5、默认情况就是懒加载

  • 集合的懒加载

    1. lazy= “false” 当session.get时,集合就被加载出来了
    2. lazy=” true” 在遍历集合的时候才加载
    3. lazy=”extra” 针对集合做count,min,max,sum等操作
  • 单端关联的懒加载(多对一)

        <many-to-one lazy="false/no-proxy/proxy">  no-porxy 默认值  true

根据多的一端加载一的一端,就一个数据,所以无所谓

总结

懒加载主要解决了一个问题:类、集合、many-to-one在时候发出SQL语句,加载数据

实例

Classes.hbm.xml

<!-- lazy  truefalseextra 进一步的懒加载   --><set name="students" cascade="save-update" inverse="true" lazy="extra" fetch="join"><!-- key是用来描述外键--><key><column name="cid"></column></key><one-to-many class="cn.itcast.hiberate.sh.domain.Student"/></set>

lazyTest.java

package cn.itcast.hibernate.sh.test;import java.util.Set;import org.hibernate.Session;
import org.junit.Test;import cn.itcast.hiberate.sh.domain.Classes;
import cn.itcast.hiberate.sh.domain.Student;
import cn.itcast.hibernate.sh.utils.HiberanteUtils;public class LazyTest extends HiberanteUtils{static{url = "hibernate.cfg.xml";}/*** 类的懒加载*/@Testpublic void testLoad(){Session session = sessionFactory.openSession();Classes classes = (Classes)session.load(Classes.class, 1L);System.out.println(classes.getCname());session.close();}/*** 集合的延迟加载*/@Testpublic void testSet(){Session session = sessionFactory.openSession();Classes classes = (Classes)session.get(Classes.class, 10L);Set<Student> students = classes.getStudents();for(Student student:students){//这个时候才要发出sql语句System.out.println(student.getSname());}session.close();}/*** 集合的延迟加载*/@Testpublic void testSet_EXTRA(){Session session = sessionFactory.openSession();Classes classes = (Classes)session.get(Classes.class, 10L);Set<Student> students = classes.getStudents();System.out.println(students.size());session.close();}
}

经典错误

could not initialize proxy no session
在关闭session后取值

抓取策略

1、研究的主要是set集合如何提取数据
2、在Classes.hbm.xml文件中

       <set fetch="join/select/subselect">join        左外连接如果把需求分析翻译sql语句,存在子查询,这个时候用该策略不起作用select      默认先查询一的一端,再查询多的一端subselect   子查询如果需要分析翻译成sql语句存在子查询,这个时候用该策略效率最高

只要查询的不是一个班级的所有学生信息的时候,就是子查询,通常来说

FetchTest.java

package cn.itcast.hibernate.sh.test;import java.util.List;
import java.util.Set;import org.hibernate.Session;
import org.junit.Test;import cn.itcast.hiberate.sh.domain.Classes;
import cn.itcast.hiberate.sh.domain.Student;
import cn.itcast.hibernate.sh.utils.HiberanteUtils;public class FetchTest extends HiberanteUtils{static{url = "hibernate.cfg.xml";}/*** n+1的问题*    解决问题的方案:子查询  fetch="subselect"*/@Testpublic void testAll_Classes(){Session session = sessionFactory.openSession();List<Classes> cList = session.createQuery("from Classes").list();for(Classes classes:cList){Set<Student> students = classes.getStudents();for(Student student:students){System.out.println(student.getSname());}}session.close();}/*** n+1的问题*    解决问题的方案:子查询  fetch="subselect"*    查询cid为1的学生*/@Testpublic void testClasses_Some(){Session session = sessionFactory.openSession();List<Classes> cList = session.createQuery("from Classes where cid in(1,2,3)").list();for(Classes classes:cList){Set<Student> students = classes.getStudents();for(Student student:students){System.out.println(student.getSname());}}session.close();}/*** 查询一个班级的所有学生 */@Testpublic void testQueryClasses_Id(){Session session = sessionFactory.openSession();Classes classes = (Classes)session.get(Classes.class, 1L);Set<Student> students = classes.getStudents();for(Student student:students){System.out.println(student.getSname());}session.close();}
}

懒加载和抓取策略结合:研究对象是set集合

fetch lazy sql 什么时候发出sql 说明
join false 存在子查询 当查询classes时把 classes和student全部查询出来 这种情况下join没有用
join true 存在子查询 当遍历student时发出查询student join没用
join true 不是子查询 在session.get(classes)时全部查询出来 这时,lazy没有用
subselect true/false 存在子查询 发出两条sql语句 如果lazy为true,在遍历集合,如果lazy为false,在一开始就发出
select true/false 发出n+1条sql 如果lazy为true,在遍历集合,如果lazy为false,在一开始就发出

缓存

session的产生方式

  1. sessionFactory.openSession 产生一个新的session
  2. sessionFactory.getCurrentSession 获取当前线程中的session

session.getCurrentSession的用法

1、在hibernate的配置文件中:

        <property name="current_session_context_class">thread</property>

2、不需要写session.close方法,在事务提交的时候会自动关闭(由hibernate内部完成)
3、crud都需要事务
1、因为是一个线程,所以整个方法中一个session,一个事务
2、保证了整个业务操作的安全性

缓存

1、缓存的生命周期
2、数据库的数据是怎么样放入到缓存中的
3、缓存中的数据是怎么样放入到数据库中的
4、客户端怎么样从缓存中把数据取出来
5、客户端怎么样把一个数据放入到缓存中
6、怎么样把一个对象从缓存中取出
7、把缓存中所有的数据清空

session缓存

1、生命周期就是session的生命周期
2、一级缓存存放的数据都是私有数据
把session存放在threadlocal中,不同的线程是不能访问的,所以保证了数据的安全性
3、怎么样把数据存放到一级缓存中
利用session.save/update/load/get方法都可以存放在一级缓存中
4、利用session.get/load方法可以把数据从一级缓存中取出
5、session.evict方法可以把一个对象从一级缓存中清空
6、利用session.clear方法可以把session中的所有的数据清空
7、利用session.Refresh方法把数据库中的数据同步到缓存中
8、session.flush
在session的缓存内部,会去检查所有的持久化对象
1、如果一个持久化对象没有ID值,则会发出insert语句
2、如果一个持久化对象有ID值,则会去检查快照进行对比,如果一样,则什么都不做,如果不一样,则发出update语句
3、检查所有的持久化对象是否有关联对象
检查关联对象的级联操作
检查关联对象的关系操作
9、批量操作

实例

package cn.itcast.hibernate.sh.test;import java.util.Set;import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;import cn.itcast.hiberate.sh.domain.Classes;
import cn.itcast.hiberate.sh.domain.Student;
import cn.itcast.hibernate.sh.utils.HiberanteUtils;public class SessionCacheTest extends HiberanteUtils{static{url = "hibernate.cfg.xml";} /*** session.get方法把数据存放在一级缓存中了*/@Testpublic void testGet(){Session session = sessionFactory.getCurrentSession();Transaction transaction = session.beginTransaction();Classes classes = (Classes)session.get(Classes.class, 1L);classes = (Classes)session.get(Classes.class,1L);transaction.commit();}/*** session.load方法把数据存放在一级缓存中*/@Testpublic void testLoad(){Session session = sessionFactory.getCurrentSession();Transaction transaction = session.beginTransaction();Classes classes = (Classes)session.load(Classes.class, 1L);classes.getCname();classes = (Classes)session.load(Classes.class,1L);classes.getCname();transaction.commit();}/*** session.save方法把数据保存在一级缓存中*/@Testpublic void testSave(){Session session = sessionFactory.getCurrentSession();Transaction transaction = session.beginTransaction();Classes classes = new Classes();classes.setCname("aaa");classes.setDescription("asfd");session.save(classes);classes = (Classes)session.get(Classes.class, classes.getCid());transaction.commit();}/*** session.update方法把数据保存在一级缓存中*/@Testpublic void testUpdate(){Session session = sessionFactory.getCurrentSession();Transaction transaction = session.beginTransaction();Classes classes = (Classes)session.get(Classes.class, 1L);session.evict(classes);//classes对象从session中清空了session.update(classes);//把classes对象放入到了session缓存中classes = (Classes)session.get(Classes.class, 1L);transaction.commit();}/*** session.clear*/@Testpublic void testClear(){Session session = sessionFactory.getCurrentSession();Transaction transaction = session.beginTransaction();Classes classes = (Classes)session.get(Classes.class, 1L);session.clear();//classes对象从session中清空了classes = (Classes)session.get(Classes.class, 1L);transaction.commit();}@Testpublic void testClearTest(){Session session = sessionFactory.getCurrentSession();Transaction transaction = session.beginTransaction();Classes classes  = (Classes)session.get(Classes.class, 1L);session.clear();//如果不加这句话,两个不同的对象,相同的ID值,所以得把其中的一个清空Classes classes2 = new Classes();classes2.setCid(1L);classes2.setCname("asfd");session.update(classes2);transaction.commit();}/*** 把数据库中的数据刷新到缓存中*/@Testpublic void testRefresh(){Session session = sessionFactory.getCurrentSession();Transaction transaction = session.beginTransaction();Classes classes = (Classes)session.get(Classes.class, 1L);classes.setCname("66");session.refresh(classes);//把cid为1的值从数据库刷到了缓存中System.out.println(classes.getCname());transaction.commit();}/*** session.flush*/@Testpublic void testFlush(){Session session = sessionFactory.getCurrentSession();Transaction transaction = session.beginTransaction();Classes classes  =(Classes)session.get(Classes.class, 1L);classes.setCname("afdsasdf");Set<Student> students = classes.getStudents();for(Student student:students){student.setDescription("asdf");}session.flush();transaction.commit();}//插入大量数据@Testpublic void testSaveBatch(){Session session = sessionFactory.getCurrentSession();Transaction transaction = session.beginTransaction();for(int i=6;i<1000000;i++){Classes classes = new Classes();classes.setCname("aaa");classes.setDescription("afds");session.save(classes);if(i%50==0){session.flush();session.clear();}}transaction.commit();}/*** session.flush只是发出SQL语句了,并没有清空session缓存*/@Testpublic void testFlush2(){Session session = sessionFactory.getCurrentSession();Transaction transaction = session.beginTransaction();Classes classes = (Classes)session.get(Classes.class, 1L);session.flush();classes = (Classes)session.get(Classes.class, 1L);transaction.commit();}
}

二级缓存

存放公有数据
1、适用场合:
1、数据不能频繁更新
2、数据能公开,私密性不是很强
2、hibernate本身并没有提供二级缓存的解决方案
3、二级缓存的实现是依赖于第三方供应商完成的
ehcache
oscache
jbosscache
swamchache
4、二级缓存的操作
1、二级缓存存在sessionFactory中
2、生命周期:与sessionFactory保持一致
3、使用二级缓存的步骤

             1、在hibernate.cfg.xml <property name="cache.use_second_level_cache">true</property><property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>2、让某一个对象进入到二级缓存中* 在配置文件中<class-cache usage="read-only" class="cn.itcast.hiberate.sh.domain.Classes"/>*  在映射文件中<cache usage="read-only"/>3、使用session.get/session.load

实例

package cn.itcast.hibernate.sh.test;import java.util.List;
import java.util.Set;import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;import cn.itcast.hiberate.sh.domain.Classes;
import cn.itcast.hiberate.sh.domain.Student;
import cn.itcast.hibernate.sh.utils.HiberanteUtils;public class SecondCacheTest extends HiberanteUtils{static{url = "hibernate.cfg.xml";} /*** session.get*    把数据存在一级缓存和二级缓存*/@Testpublic void testGet(){Session session = sessionFactory.openSession();Classes classes = (Classes)session.get(Classes.class, 1L);session.close();session = sessionFactory.openSession();classes = (Classes)session.get(Classes.class, 1L);session.close();}/*** session.load*   同上*/@Testpublic void testLoad(){Session session = sessionFactory.openSession();Classes classes = (Classes)session.load(Classes.class, 1L);classes.getCname();session.close();session = sessionFactory.openSession();classes = (Classes)session.load(Classes.class, 1L);classes.getCname();session.close();}/*** session.update   * */@Testpublic void testUpdate(){Session session = sessionFactory.openSession();//session.beginTransaction();Classes classes = new Classes();classes.setCid(1L);classes.setCname("aaa");session.update(classes);session.close();session = sessionFactory.openSession();classes = (Classes)session.get(Classes.class, 1L);session.close();}@Testpublic void testAllClasses(){Session session = sessionFactory.openSession();List<Classes> classesList = session.createQuery("from Classes").list();session.close();try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}
}

查询缓存

使用方式,在classes.hbm.xml中开启 开启true

实例

package cn.itcast.hibernate.sh.test;import java.util.List;
import java.util.Set;import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;import cn.itcast.hiberate.sh.domain.Classes;
import cn.itcast.hiberate.sh.domain.Student;
import cn.itcast.hibernate.sh.utils.HiberanteUtils;public class QueryCacheTest extends HiberanteUtils{static{url = "hibernate.cfg.xml";} @Testpublic void testQuery(){Session session = sessionFactory.openSession();Query query = session.createQuery("from Classes");query.setCacheable(true);//classes里的所有的数据要往查询缓存中存放了List<Classes> classesList = query.list();query = session.createQuery("from Classes");query.setCacheable(true);classesList = query.list();session.close();}
}

二级缓存大量数据解决方案,将一部分数据存储在磁盘中

在src文件夹下添加ehcache.xml

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"><diskStore path="C:\\TEMP1"/><defaultCache
            maxElementsInMemory="12"eternal="false"timeToIdleSeconds="120"timeToLiveSeconds="120"overflowToDisk="false"maxElementsOnDisk="10000000"diskPersistent="false"diskExpiryThreadIntervalSeconds="120"memoryStoreEvictionPolicy="LRU"/><Cache
            name="cn.itcast.hiberate.sh.domain.Classes"maxElementsInMemory="5" eternal="false"timeToIdleSeconds="120"timeToLiveSeconds="120"overflowToDisk="true"maxElementsOnDisk="10000000"diskPersistent="false"diskExpiryThreadIntervalSeconds="120"memoryStoreEvictionPolicy="LRU"/>
</ehcache>

示例

@Testpublic void testAllClasses(){Session session = sessionFactory.openSession();List<Classes> classesList = session.createQuery("from Classes").list();session.close();try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}

完成

Hibernate之性能优化相关推荐

  1. Hibernate程序性能优化的考虑要点

    Hibernate程序性能优化的考虑要点 Tag:java,j2ee,hibernate,O/R mappling, spring,性能,效率 本文依照HIBERNATE帮助文档,一些网络书籍及项目经 ...

  2. Hibernate查询性能优化技巧

    数据库查询性能的提升也是涉及到开发中的各个阶段,在开发中选用正确的查询方法无疑是最基础也最简单的. SQL语句的优化 使用正确的SQL语句可以在很大程度上提高系统的查询性能.获得同样数据而采用不同方式 ...

  3. 【Hibernate】性能优化之缓存管理

    1.缓存概述 缓存(cache)在java应用程序中是一组内存中的集合示例,它保存着永久性存储源(如硬盘上的文件或数据库)中数据的备份,它的读写速度比读写硬盘的速度快.应用程序在运行时直接读写缓存中的 ...

  4. Hibernate性能优化之EHCache缓存

    像Hibernate这种ORM框架,相较于JDBC操作,需要有更复杂的机制来实现映射.对象状态管理等,因此在性能和效率上有一定的损耗. 在保证避免映射产生低效的SQL操作外,缓存是提升Hibernat ...

  5. Hibernate性能优化

    有很多人认为Hibernate天生效率比较低,确实,在普遍情况下,需要将执行转换为SQL语句的 Hibernate的效率低于直接JDBC存取,然而,在经过比较好的性能优化之后,Hibernate的性能 ...

  6. 推荐:Java性能优化系列集锦

    Java性能问题一直困扰着广大程序员,由于平台复杂性,要定位问题,找出其根源确实很难.随着10多年Java平台的改进以及新出现的多核多处理器,Java软件的性能和扩展性已经今非昔比了.现代JVM持续演 ...

  7. ASP.Net服务性能优化原则

    理理Asp.net性能相关的问题及注意事项.   以下这些内容,全部是经验之谈.如果你有别的建议,也可以从后台发给我.   服务器性能问题,通常在数据少的时候不会显现,也无需太多关注.但一旦数据量大了 ...

  8. java常见性能优化_十大最常见的Java性能问题

    java常见性能优化 Java性能是所有Java应用程序开发人员都关心的问题,因为快速使应用程序与使其正常运行同等重要. 史蒂文·海恩斯(Steven Haines)使用他在Java性能问题上的个人经 ...

  9. 一文了解 Java 应用程序性能优化指南

    点击上方"CSDN",选择"置顶公众号" 关键时刻,第一时间送达! 在<2018 最具就业前景的 7 大编程语言>一文中,通过分析了来自 Indee ...

最新文章

  1. NHibernate初学二之简单执行SQL及HQL、Linq
  2. jquery、js父子页面操作总结
  3. Spring 已经实现的线程池
  4. 使用@Valid进行Spring验证bindingresult 用法
  5. javascript图书
  6. qmoc文件_Qt中Q_OBJECT与生成的moc文件的作用
  7. 收藏|2021年阿里云开源镜像站最热门镜像王全梳理(附下载链接和Top20镜像王排名)
  8. UEditor工具栏上自定义按钮、图标、事件、窗口页面
  9. 原码、反码、补码详述
  10. 再谈初学者关心的ssh应用方方面面
  11. 【穷举】用c#实现一个数组(1,1,2,2,3,3,4,4)排列,每两个相同数字中间都间隔了这个数字个数...
  12. poj 1151 hdu 1542 Atlantis 线段树扫描线(详细讲解)
  13. GD32F103移植FreeRTOS
  14. 量子统计巨正则系综应用理想费米气体与波色气体性质详解
  15. 用口诀背英语单词绿色版简介
  16. 在ubuntu9.04中安装电视卡用到的资料
  17. 2019(第八届)国际桥梁与隧道技术大会-会议议程
  18. uva 10827 Maximum sum on a torus
  19. VIP网易邮箱,163VIP邮箱,新浪vip等邮箱的对比分析
  20. js将秒转为天时分秒格式

热门文章

  1. 改变世界,改善生活:我从科沃斯扫地机器人X1,看到了AI新的希望
  2. 深度推荐系统2019年度阅读收藏清单
  3. Step-by-step to LSTM: 解析LSTM神经网络设计原理
  4. 论文浅尝 | 弱监督关系抽取的深度残差学习方法
  5. Android官方开发文档Training系列课程中文版:多样屏幕之支持不同的屏幕密度
  6. 【Tensorflow】打印输出tensor张量和变量的方法
  7. JAVA:线程总结及多线程实现的两种方法
  8. day20 面向对象编程
  9. 第二阶段个人工作总结08
  10. 分享-利用VPC防止病毒软件的进入你的windows电脑