Hibernate3.3(5)

    xiaoxiao2021-12-14  16

     1.      懒加载是什么? 为什么需要懒加载?

     

    2.      如何解决懒加载问题

     

    u  为什么需要缓存?

    看一个案例:->原理图

    从上图看出: 当我们去查询对象的时候,首先到一级缓存去取数据,如果有,则不到数据库中取,如果没有则到数据库中取,同时在一级缓存中放入对象.

    u  一级缓存的细节

    ①      什么操作会向一级缓存放入数据

    save,update,saveOrUpdate,load,get,list,iterate,lock

    save 案例:

           //添加一个学生

                         Studentstudent=new Student();

                         student.setName("小东");

                        

                         s.save(student);//放入一级缓存

                        

                         //我马上查询

                         Studentstu2=(Student) s.get(Student.class, student.getId()); //select

                         System.out.println("你刚刚加入的学生名字是"+stu2.getName());

    ②      什么操作会从一级缓存取数据.

    get / load / list

     

    get / load 会首先从一级缓存中取,如没有.再有不同的操作[get 会立即向数据库发请求,而load 会返回一个代理对象,直到用户真的去使用数据,才会向数据库发请求]

    ?list 会不会从session缓存取数据?

    案例:

    //查询45号学生

                 

                         Studentstu=(Student) s.get(Student.class, 45);

                        

                         System.out.println("|||||||||||||||||||");

                        

                         Stringhql="from Student where id=45";

                        

                        

                         Studentstu2=(Student) s.createQuery(hql).uniqueResult();

                        

                         System.out.println(stu2.getName());

    从上面的案例,我看出query.list() query.uniueResut() 不会从一级缓取数据! 但是query.list 或者query.uniqueRestu() 会向一级缓存放数据的.

    ③      一级缓存不需要配置,就可以使用,它本身没有保护机制,所以我们程序员要考虑这个问题,我们可以同 evict 或者 clear来清除session缓存中对象. evict 是清除一个对象,clear是清除所有的sesion缓存对象

    ④      session级缓存中对象的生命周期, 当session关闭后,就自动销毁.

    ⑤      我们自己用HashMap来模拟一个Session缓存,加深对缓存的深入.

    package com.hsp.view;

     

    import java.util.ArrayList;

    import java.util.HashMap;

    import java.util.List;

    import java.util.Map;

    public class MyCache {

           //使用map来模拟缓存

           staticMap<Integer,Student> maps=new HashMap<Integer,Student>();

     

           publicstatic void main(String[] args) {

                  // TODO Auto-generated method stub

     

                  getStudent(1);

                  getStudent(1);

                  getStudent(1);

                  getStudent(1);

                  getStudent(3);

                  getStudent(3);

                 

                 

                 

           }

          

           public static Student getStudent(Integerid){  //s.get()

                 

                 

                  //先到缓存去

                  if(maps.containsKey(id)){

                         //在缓存有

                         System.out.println("从缓存取出");

                         returnmaps.get(id);

                  }else{

                         System.out.println("从数据库中取");

                         //到数据库取

                         Studentstu=MyDB.getStudentFromDB(id);

                         //放入缓存

                         maps.put(id,stu);

                         returnstu;

                  }

                 

          

                 

           }

     

    }

     

    //我的数据库

    class MyDB{

          

           staticList<Student> lists=new ArrayList<Student>();

          

           //初始化数据库,假设有三个学生

           static{

                  Students1=new Student();

                  s1.setId(1);

                  s1.setName("aaa");

                  Students2=new Student();

                  s2.setId(2);

                  s2.setName("bbb");

                  Students3=new Student();

                  s3.setId(3);

                  s3.setName("ccc");

                  lists.add(s1);

                  lists.add(s2);

                  lists.add(s3);

                 

           }

          

           publicstatic Student getStudentFromDB(Integer id){

                  for(Students: lists){

                         if(s.getId().equals(id)){

                                returns;

                         }

                  }

                  returnnull;// 在数据库中没有.

                 

           }

    }

     

    class Student{

           privateInteger id;

           privateString name;

           publicInteger getId() {

                  returnid;

           }

           publicvoid setId(Integer id) {

                  this.id= id;

           }

           publicString getName() {

                  returnname;

           }

           publicvoid setName(String name) {

                  this.name= name;

           }

    }

     

    u  为什么需要二级缓存?

    因为一级缓存有限(生命周期短),所以我们需要二级缓存(SessionFactory缓存)来弥补这个问题

    1.      需要配置

    2.      二级缓存是交给第三方去处理,常见的Hashtable ,OSCache , EHCache

    3.      二级缓存的原理

    4.      二级缓存的对象可能放在内存,也可能放在磁盘.

     

    u  快速入门案例

    使用OsCache来演示二级缓存的使用.

     

    1.      配置二级缓存

     

    对配置说明:

    <propertyname="hbm2ddl.auto">update</property>

           <!--启动二级缓存 -->

           <property name="cache.use_second_level_cache">true</property>

           <!--指定使用哪种二级缓存-->

           <propertyname="cache.provider_class">org.hibernate.cache.OSCacheProvider</property>

           <mappingresource="com/hsp/domain/Department.hbm.xml" />

           <mappingresource="com/hsp/domain/Student.hbm.xml" />

           <!--指定哪个domain启用二级缓存

           特别说明二级缓存策略:

           1.read-only

           2.read-write

           3.nonstrict-read-write

           4.transcational

           -->

           <class-cache class="com.hsp.domain.Student"usage="read-write"/>

    2. 可以文件放在 src目录下,这样你可以指定放入二级缓存的对象capacity 大小. 默认1000

    3 使用

    // TODO Auto-generated method stub

                  //通过获取一个sesion,让hibernate框架运行(config->加载hibernate.cfg.xml)

                  Sessions=null;

                  Transactiontx=null;

                 

                  try{

                         //我们使用基础模板来讲解.

                         s=HibernateUtil.openSession();

                         tx=s.beginTransaction();

                        

                         //查询45号学生

                 

                         Studentstu1=(Student) s.get(Student.class, 45);//45->一级缓存       

                         System.out.println(stu1.getName());

                        

                        

                         tx.commit();

                        

                  }catch (Exception e) {

                         e.printStackTrace();

                         if(tx!=null){

                                tx.rollback();

                         }

                  }finally{

                        

                         if(s!=null&& s.isOpen()){

                                s.close();

                         }

                  }

                 

                  System.out.println("*********************************");

                  try{

                         //我们使用基础模板来讲解.

                         s=HibernateUtil.openSession();

                         tx=s.beginTransaction();

                        

                         //查询45号学生

                 

                         Studentstu1=(Student) s.get(Student.class, 45);  

                         System.out.println(stu1.getName());

                        

                         Studentstu3=(Student) s.get(Student.class, 46);  

                         System.out.println(stu3.getName());

                                tx.commit();

                        

                  }catch (Exception e) {

                         e.printStackTrace();

                         if(tx!=null){

                                tx.rollback();

                         }

                  }finally{

                        

                         if(s!=null&& s.isOpen()){

                                s.close();

                         }

                  }

                 

                  //完成一个统计,统计的信息在Sessfactory

                  //SessionFactory对象.

                  Statisticsstatistics= HibernateUtil.getSessionFactory().getStatistics();

                  System.out.println(statistics);

                  System.out.println("放入"+statistics.getSecondLevelCachePutCount());

                  System.out.println("命中"+statistics.getSecondLevelCacheHitCount());

                  System.out.println("错过"+statistics.getSecondLevelCacheMissCount());

    3. 在配置了二级缓存后,请大家要注意可以通过Statistics,查看你的配置命中率高不高

     

     

    u  主键增长策略

    ①      increment

    自增,每次增长1, 适用于所有数据库. 但是不要使用在多进程,主键类型是数值型

    select max(id) from Student

    ②    identity

    自增,每次增长1, 适用于支持identity的数据(mysql,sqlserver), 主键类型是数值

    ③    sequence

    ④    native

    会根据数据类型来选择,使用identity,sequence ,hilo

    selecthibernate_sequence.nextval from dual

    主键类型是数值long , short ,int

    <id name="id"type="java.lang.Integer">

    <generatorclass="native"/>

    </id>

    ⑤    hilo

    hilo标识符生成器由Hibernate按照一种high/low算法生成标识符

    用法:

    <id name=”id” type=”java.lang.Integer” column=”ID”>

        <generatorclass=”hilo”>

       <paramname=”table”>my_hi_value</param>

       <param name=”column”>next_value</param>

        </generator>

        </id>

    ⑥    uuid

    会根据uuid算法,生成128-bit的字串

    主键属性类型不能是数值型,而是字串型

    ⑦    assigned

    用户自己设置主键值,所以主键属性类型可以是数值,字串

    ⑧    映射复合主键

    ⑨    foreign

    在one-to-one的关系中,有另一张表的主键(Person) 来决定 自己主键/外键( IdCard)

     

    给出一个简单原则:

    针对oracle [主键是int/long/short 建议使用 sequence] 主键是String 使用uuid或者assinged

    针对 mysql [主键是 int/long/short 建议使用increment/assigend,如果是字串 UUId/assigned]

    针对 sql server [主键是 int/long/short 建议使用identity/native/assinged ,如果主键是字串,使用uuid/assigned ]

     

    one-to-one 又是基于主键的则使用foreign

     

    u  hibernate最佳实践(在什么项目中使用最好)

    对于数据量大,性能要求高系统,不太使用使用hiberante.

    主要用于事务操作比较多的项目(oa/某个行业软件[石油、税务、crm, 财务系统.]

     

    olap->hibernate用的比较少  oltp->hibernate

     

    转载请注明原文地址: https://ju.6miu.com/read-969673.html

    最新回复(0)