日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Hibernate之性能优化

發布時間:2024/7/23 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Hibernate之性能优化 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文主要包括以下內容

性能優化的方法

發出的sql語句越少,性能越高
方法:
1、懶加載
2、抓取策略
3、緩存策略
4、HQL語句

懶加載

  • 類的懶加載
    1、利用session.load方法可以產生代理對象
    2、在session.load方法執行的時候并不發出sql語句
    3、在得到其一般屬性的時候發出sql語句
    4、只針對一般屬性有效,針對標示符屬性是無效的
    5、默認情況就是懶加載

  • 集合的懶加載

  • lazy= “false” 當session.get時,集合就被加載出來了
  • lazy=” true” 在遍歷集合的時候才加載
  • 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的產生方式

  • sessionFactory.openSession 產生一個新的session
  • 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之性能优化的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。