传智播客hibernate视频教程-读书笔记3

来源:互联网 发布:支付宝和淘宝怎么绑定 编辑:程序博客网 时间:2024/05/19 19:40

21~56讲

 

10、多对多(teacher-student)
    性能不佳,一般会拆成两个一对多,hibernate会创建中间表做关联。
   Teacher(id,name,students)  -->private Set<Student> students
   Student(id,name,teachers)  -->private Set<Teacher> teachers
   Teacher.hbm.xml中定义:
       <class name="Teacher">
    <id name="id">
       <generator class="native"/>
    </id>
  
    <property name="name"/>

    <set name="students" table="teacher_student">   --->中间表
               <key column="teacher_id"/>
        <many-to-many class="Student" column="student_id"/>
           </set>
 </class>

   Student.hbm.xml中定义(与上类似):
       <class name="Student">
    <id name="id">
       <generator class="native"/>
    </id>
  
    <property name="name"/>

    <set name="teachers" table="teacher_student">   --->中间表
               <key column="student_id"/>
        <many-to-many class="Teacher" column="teacher_id"/>
           </set>
 </class>

    插入操作代码:
    Student stu1 = new Student();
    stu1.setName("stu1");
    Student stu2 = new Student();
    stu2.setName("stu2");
    Set<Student> s = new HashSet<Student>(); //也可以定义HashSet<Teacher> ,让学生知道老师,但两种方式不能并存
    s.add(stu1);
    s.add(stu2);
  
    Teacher tea1 = new Teacher();
    tea1.setName("tea1");
    Teacher tea2 = new Teacher();
    tea2.setName("tea2");
   
    tea1.setStudents(s);
    tea2.setStudents(s);    //老师知道学生


11、组件映射(User)
    同多对一和一对多,后两者是将复杂属性(非基本类型,如自定义的Name类)分到另外一张表中与User关联,而组件关联则是全部放在当前表中展现,其他无区别
    例如User有Name属性,Name类包括firstName和lastName两个属性。
    User.hbm.xml中定义:
    <!--
       <property name="name"/>
    -->
    <component name="name">
       <property name="firstName" column="first_name"/>
       <property name="lastName" column="last_name"/>
    </component>

    则数据库User表中字段有(id,first_name,last_name),而不是(id,name_id)

12、hibernate中的集合类型
   
    1)将一对多中Department的emps的类型改为List
      Department(id,name,emps)   -->private List<Employee> emps
      Department.hbm.xml中定义:
      <list name="emps">
         <key column="depart_id"/> 
         <list-index column="order_co"/>  ---->供hibernate记下每个记录的添加顺序,该列存在Employee表中
  <one-to-many class="Employee"/>
      </list>

     想在代码中用List类型,但是又不想hibernate因为list排序而耗性能,可以使用bag标签(与list一样,但是无需保证顺序)
      <bag name="emps">
         <key column="depart_id"/> 
  <one-to-many class="Employee"/>
      </bag>
    

    2)将一对多中Department的emps的类型改为Map
      Department(id,name,emps)   -->private Map<String,Employee> emps
      Department.hbm.xml中定义:
      <map name="emps">
         <key column="depart_id"/> 
         <map-key type="string" column="name"/>
  <one-to-many class="Employee"/>
      </map>

13、关联关系的级联操作
    默认hibernate是不进行级联操作的,例如保存Department时,不会自动保存Employee对象。
    可以在Department.hbm.xml中修改一下
    <set name="emps" cascade="save-update">
    则代码中仅需save(depart),而无需save(employee)

    常用cascade有:none(默认)、all、save-update、delete....标签中多个时逗号分割
    一般对many-to-one,many-to-many不设置级联,在one-to-one,one-to-many中设置级联

14、懒加载(提高性能,将和数据库交互的时间延后)
    1)load
    User user = s.load(User.class,id);
    Hibernate.initialize(user);  ---->强迫此处load方法生成的代理user初始化一下(类似在当前的session范围中访问一下数据库),则后续在离开这个session范围后,使用user代理不会报错。
   
    2)one-to-one懒加载
    必须同时满足如下三个条件才能实现懒加载(只对从表有效,如IDCard,查询get(IDCard.class,id)时,不会查询Person)
    lazy!=false --默认
    constrained=true(主表不能设置如此)
    fetch=select  --默认

    3)one-to-many懒加载
    必须同时满足如下两个条件才能实现懒加载
    lazy!=false --默认
    fetch=select --默认

    4)many-to-one懒加载
    必须同时满足如下两个条件才能实现懒加载
    lazy!=false --默认
    fetch=select --默认

    5)many-to-many懒加载
    必须同时满足如下两个条件才能实现懒加载
    lazy!=false --默认
    fetch=select --默认

15、缓存
    1)一级缓存(Session)
    save,update,saveOrUpdate,load.get,list,iterate,lock这些方法都会将对象放在一级缓存中。
    一级缓存不能控制缓存的数量,所以要注意内存溢出,可通过evict,clear方法清除缓存中的内容。
    get和load方法会先去缓存中找。

    2)二级缓存(SessionFactory)
    hibernate.cfg.xml中配置
    cache.use_second_level_cache:true  默认,可不配
    cache.provider_class: org.hibernate.cache.OSCacheProvider (增加相应lib包)

    指定要缓存的类
    <class-cache class="org.hibernate.test.User" usage="read-only"/>  usage:read-only,read-writer....
    或在User.hbm.xml中指定
    <class name="User">
      <cache usage="read-only"/>
    ....

    save,update,saveOrUpdate,list,iterator,get,load以及Query,Criteria都会填充二级缓存,但是只有Session的iterator,get,load会从二级缓存中查询数据。
   
    统计信息打开generate_statistics,用sessionFactory.getStatistics()获取统计信息。

    SessionFactory.evict(User.class)/SessionFactory.evict(User.class,id)清除缓存。

    Hibernate首先从一级缓存中寻找,找不到再到二级缓存中寻找。

16、Session是非线程安全,SessionFactory是线程安全的。

原创粉丝点击