Hibernate之性能优化

本文主要包括以下内容

性能优化的方法

发出的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集合

fetchlazysql什么时候发出sql说明
joinfalse存在子查询当查询classes时把 classes和student全部查询出来这种情况下join没有用
jointrue存在子查询当遍历student时发出查询studentjoin没用
jointrue不是子查询在session.get(classes)时全部查询出来这时,lazy没有用
subselecttrue/false存在子查询发出两条sql语句如果lazy为true,在遍历集合,如果lazy为false,在一开始就发出
selecttrue/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();}

完成

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/494207.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java学习笔记之数组

数组是一种效率最高的存储和随机访问对象引用序列的方式,一旦初始化完成&#xff0c;数组长度将不能变&#xff0c;但可以改变其引用&#xff0c;如&#xff1a; int a[]{1,2}; int b[]{1,2,3,4,5}; ab; 如果输出&#xff0c;将得到&#xff1a; b.length5;a.length5; java数组…

《爬虫写得好,铁窗关到老》教你把握爬虫的法律边界!㊫

作者简介 蓝桥签约作者、大数据&Python领域优质创作者。维护多个大数据技术群&#xff0c;帮助大学生就业和初级程序员解决工作难题。 我的使命与愿景&#xff1a;持续稳定输出&#xff0c;赋能中国技术社区蓬勃发展&#xff01; 最近的IT公司违法案件越来越多&#xff0c;…

Android学习总结00之废话

前几天终于将《Android开发从零开始》共43个视频看完&#xff0c;在此简单的做一下总结。本来起了个题目叫《Android开发从零开始》学习后记&#xff0c;后来感觉太长了&#xff0c;起个短一点的名字《Android学习总结》&#xff0c;既然不叫《Android开发从零开始》学习后记的…

23篇大数据系列(三)sql基础知识(史上最全,建议收藏)

作者简介 蓝桥签约作者、大数据&Python领域优质创作者。维护多个大数据技术群&#xff0c;帮助大学生就业和初级程序员解决工作难题。 我的使命与愿景&#xff1a;持续稳定输出&#xff0c;赋能中国技术社区蓬勃发展&#xff01; 大数据系列文章&#xff0c;从技术能力、…

脑机交互研究及标准化实践

来源&#xff1a; 人机与认知实验室摘要&#xff1a;本文介绍脑机交互的概念及标准化的必要性&#xff0c;讨论近年来脑机交互的发展状况&#xff0c;重点阐述国内外植入式脑机接口的研究历程&#xff0c;并从脑机交互系统角度提出了脑机交互标准化的思考&#xff0c;同时介绍在…

C#反射的特性

如果您现在对反射还不太了解的话&#xff0c;那么可以先看看这篇博文&#xff0c;来粗略的了解一下反射吧。什么是反射 反射特性&#xff08;Attribute&#xff09;  1. C#内置特性介绍  特性是一个对象&#xff0c;它可以加载到程序集及程序集的对象中&#xff0c;这些对象…

Spring基础知识

本文主要包括以下内容 注解 注解 1、注解就是为了说明java中的某一个部分的作用(Type) 2、注解都可以用于哪个部门是Target注解起的作用 3、注解可以标注在ElementType枚举类所指定的位置上 4、 Documented //该注解是否出现在帮助文档中 Retention(Retenti…

拥抱人工智能报告:中国未来就业的挑战与应对

来源&#xff1a; 199IT互联网数据中心近日&#xff0c;中国发展研究基金会联合红杉资本中国基金&#xff0c;对外发布了一份名为《投资人力资本&#xff0c;拥抱人工智能&#xff1a;中国未来就业的挑战与应对》的研究报告。在这篇报告中&#xff0c;研究课题组对比中外、调研…

《Python 快速入门》C站最全Python标准库总结

点赞 ➕ 评论 ➕ 收藏 养成三连好习惯 &#x1f345; 联系作者&#xff1a; 不吃西红柿 &#x1f345; 作者简介&#xff1a;CSDN 博客专家丨全站 Top 10&#x1f3c6;、HDZ 核心组成员、信息技术智库公号号主 &#x1f345; 简历模板、PPT 模板、学习资料、技术互助。关注…

工业4.0进行时:未来协作方式的变革

来源&#xff1a;资本实验室协作是将人类智力发挥至极致的方式&#xff0c;也是推动人类社会进步的重要手段。随着各种新技术的发展与应用&#xff0c;人类之间的协作方式也在随着技术的进步而进步。从面对面交流&#xff0c;到电话与传真、电子邮件与OA系统&#xff0c;再到在…

java之代理设计模式

代理模式是常用的java设计模式&#xff0c;他的特征是代理类与委托类有同样的接口&#xff0c;代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类&#xff0c;以及事后处理消息等。代理类与委托类之间通常会存在关联关系&#xff0c;一个代理类的对象与一个委托…

lisp中的*,**,***

在lisp中“*”除了乘法的作用外&#xff0c;还被用来保存REPL&#xff08;read-eval-print-loop&#xff09;中的返回值。其中 * -> 保存最后一次返回值。 ** -> *的上一次值。 *** -> **的上一次值。 例子如下&#xff1a; 而且  * (car /) ** …

《Python 快速入门》一千个程序员有一千套编码规范

一千个读者有一千个哈姆莱特。 -- 莎士比亚 一千个程序员有一千套编码规范。 -- 不吃西红柿 目录 1、分号 2、命名 3、行长度 4、缩进 5、空行 6、空格 7、类 8、块注释和行注释 9、字符串 10、导包 【总结】 1.命名 2.空白 3.语句 4.注释 Python 编码…

为了帮粉丝完成毕业设计,我发现了一款私活神器

一、缘起 不日前&#xff0c;有粉丝找到我&#xff0c;让我帮着做个&#xff1a; 教师管理系统 由于种种借口&#xff0c;我当时把问题交给群友去解决了..... 思来想去&#xff0c;越想越内疚&#xff0c;于是就请教了经常做私活的小伙伴。 必须分享给更多的小伙伴~ 二、揭开面…

狗脸识别APP整合

本文主要包括以下内容 android studio中导入so文件 通过URI获得Bitmap android studio中导入so文件 在main文件夹下建立jniLibs目录&#xff0c;并将so文件拷贝进去即可。 注意 声明的native方法与so文件中定义的方法的包名必须相同 通过URI获得Bitmap private Bitmap …

解析丰田对自动驾驶汽车的愿景:打造更加安全的汽车

丰田高管约翰莱昂纳德在丰田研究所的麻省理工学院车库&#xff0c;在他身后是研究所改造的一辆雷克萨斯选自&#xff1a;Bloomberg来源&#xff1a; 网易科技参与&#xff1a;乐邦约翰莱昂纳德(John Leonard)漫步走到麻省理工学院(MIT)校园里一间单调乏味的一层车库&#xff0c…

C#用IrisSkin4.dll 美化Winform窗体

前期准备&#xff1a; 1、IrisSkin4.dll2、Skin文件&#xff0c;后缀名为.ssk3、一个WinForm程序 直接拷贝IrisSkin4.dll文件到系统目录里&#xff1a;1、Windows 95/98/Me系统&#xff0c;将dll复制到C:\Windows\System目录下。2、Windows NT/2000系统&#xff0c;将dll复制到…

luogu题目精讲(C++):【入门1】顺序结构(1~5题)

B2002 Hello,World! # Hello,World! ## 题目描述 编写一个能够输出 Hello,World! 的程序。 提示&#xff1a; - 使用英文标点符号&#xff1b; - Hello,World! 逗号后面**没有**空格。 - H 和 W 为**大写**字母。 ## 输入格式 ## 输出格式 ## 样例 #1 ### 样例输入 #1 …

C站最全Python库总结丨标准库+高级库

梦想还是要有的&#xff0c;万一别人问呢&#xff1f; 作者&#xff1a;不吃西红柿 简介&#xff1a;CSDN博客专家、蓝桥签约作者、大数据&Python领域优质创作者。 CSDN私信我&#xff0c;回复【资料】领取&#xff1a; 1、100套小编购买的简历模板&#xff1b; 2、1000套…

postgresql命令

转自&#xff1a;http://blog.sina.com.cn/s/blog_4b93170a01000b2i.html1.PostgresSQL 支持标准的 SQL 类型 int&#xff0c;smallint&#xff0c; real&#xff0c;double precision&#xff0c; char(N)&#xff0c; varchar(N)&#xff0c;date&#xff0c; time&#xff0…