Hibernate小结

1、Hibernate

1、简介

  • 基于ORM

2、基本使用步骤

1、引入Hibernate核心jar包

  • Hibernate3.jar+required目录中所有+jpa+数据库驱动包

2、配置文件hibernate.cfg.xml




  
      
      jdbc:mysql:///hib_demo
      com.mysql.jdbc.Driver
      root
      root
      
      org.hibernate.dialect.MySQLDialect

      
  

3、配置映射文件(xxx.hbm.xml)







    
        
    
    
    

4、测试类

    // 对象
    Users users = new Users();
    users.setUserName("Jack");
    users.setAge(30);

    // 1. 创建配置管理器对象
    Configuration config = new Configuration();
    // 2. 加载主配置文件, 默认加载src/hibernate.cfg.xml
    config.configure();
    // 3. 根据加载的主配置文件,创建对象
    SessionFactory sf = config.buildSessionFactory();
    // 4. 创建Session对象
    Session session = sf.openSession();
    // 5. 开启事务
    Transaction tx = session.beginTransaction();

    // --- 保存
    session.save(users);

    // 6. 提交事务/关闭session
    tx.commit();
    session.close();

3、Hibernate Api

1、Session
一个与数据库连接的会话信息, Sesison里面维护了一个连接对象,且对常用操作进行封装。

  • 保存对象

    session.save(obj);
    
  • 主键查询

    Users u = (Users) session.get(Users.class, 1);//查询的主键不存在,返回null
    或Session.load(clazz,id);   //查询的主键不存在只要使用就报错
    
  • 删除

    Object obj = session.get(Users.class, 21);
    if (obj != null) {
      session.delete(obj);
    }
    
  • 修改

    Users u = new Users();
    u.setUserId(30000);  //主键一定要在数据库存在
    u.setAge(30);
    session.update(u);
    
  • 保存或更新

    Users u = new Users();
    u.setUserId(5);
    u.setUserName("Jacky001");
    session.saveOrUpdate(u);//如果有设置主键且主键存在执行更新
    
  • HQL查询

    // 得到hql查询接口
    Query q = session.createQuery("from Users");
    // 查询数据
    List list = q.list(); 
    
  • criteria 查询 ,完全面向对象的查询

    // 获取Criteria接口
    Criteria c = session.createCriteria(Users.class);
    // 设置条件
    c.add(Restrictions.eq("userName", "Jacky001"));
    List list = c.list();
    

4、hibernate.cfg.xml配置详解

1、查看配置提示

  • hibernate-distribution-3.6.0.Final\project\etc\hibernate.properties

2、自动建表

  • 配置方式

      
      true
      
      
      update
    
      #hibernate.hbm2ddl.auto create-drop    每次在创建sessionFactory的时候创建表,执行sf.close()删除表。
      #hibernate.hbm2ddl.auto create         每次都先删除表,再创建新的表
      #hibernate.hbm2ddl.auto update        如果表不存在则创建,存在就不创建!
      #hibernate.hbm2ddl.auto validate       检查映射配置与数据库结构是否一致,不一致就报错!  (严格)
    
  • 代码方式

      // 创建配置管理器对象,加载主配置文件(会加载映射)
      Configuration cfg = new Configuration().configure();
      // 自动建表工具类
      SchemaExport export = new SchemaExport(cfg);
      // 创建表
      // 第一个参数: 是否打印建表语句到控制台
      // 第二个参数: 是否执行脚本,生成表
      export.create(true, true);
    

5、映射配置

1、映射文件

  • 命名:*.hbm.xml

  • 作用: 描述“对象”与“表”的映射关系,通过映射文件可以描述一张完整的表。

  • 配置详解

    
    
    
    
    
      
      
          
          
              
          
          
          
          
          
          
          
          
          
          
      
      
    
    
    

6、联合主键映射

1、步骤

  • 联合主键对象

    public class CompositeKeys implements Serializable{
    
      private String name;
      private String address;
    
    }
    
  • bean

    // 员工
    public class Employee {
    
        // 联合主键对象
        private CompositeKeys keys;
        private String dept;
        private Date birth;
        ..
    } 
    
  • Employee的映射

      
      
    
      
          
              
                  
                  
              
              
              
              
              
              
              
              
          
      
    

7、hibernate对象状态

1、临时状态

  • 直接new出来的对象
  • 不处于session的管理(即没有与任何一个session关联)
  • 对象在数据库中没有对应的记录

2、持久化状态

  • 处于session的管理范围,当执行session的方法如:save/update/saveOrUpdate/get/load对象就会自动转变为持久化状态
  • 在数据库中有对应的记录
  • 处于持久化状态的对象,当对对象属性进行更改的时候,提交事务更改会反映到数据库中

3、游离状态

  • 对象不处于session的管理范围,通常指session关闭后对象的状态
  • 对象在数据库中有对应的记录

4、转化实例

    Session session = sf.openSession();
    session.beginTransaction();
    
    // 创建对象                             【临时状态】
    Employee emp = new Employee();
    emp.setName("Rose");
    emp.setBirth(new Date());
    
    // 保存
    session.save(emp);                  // 【持久化状态】
    emp.setName("Lucy..");              // 修改会反映到数据库中,所以这里会生成update语句
    
    session.getTransaction().commit();
    session.close();

    emp.setName("New Lucy");
    System.out.println(emp.getName());   // 此时对象处于【游离状态】

8、 Session缓存

1、概念

  • Session缓存,也叫做一级缓存;
  • 当执行session的相关方法,如: save()/update()/get()/load()等方法的时候,对象会自动放入一级缓存中;
  • 当Session关闭后,一级缓存内容失效。

2、特点

  • 缓存有效范围,只在当前session范围内有效,缓存时间很短、作用范围小;
  • 一级缓存,可以在短时间内多次操作数据库的时候,才会明显提升效率;
  • 一级缓存的结构:Ma<主键,对象>;
  • 在提交事务时候,Hibernate会同步缓存数据到数据库中,会对比缓存数据与数据库数据是否一致,如果不一致,才提交更改到数据库(生成update);
  • hibernate提供的一级缓存有hibernate自身维护,如果想操作一级缓存内容,必须通过hibernate提供的方法:
    session.flush(): 手动让让一级缓存内容与数据库同步
    session.evict(emp1): 清空一级缓存中对象,清除指定的对象
    session.clear(); 清空所有缓存

9、list()与iterator()查询区别

1、list(通常使用频率较高)

  • Query接口定义的list查询方法,一次查询所有满足需要的数据。

2、iterator

  • Query接口定义的iterator查询方法,先查询所有满足条件记录的主键 (查询1次)
    再根据每一个id,进行主键查询,有多少记录,查询多少次 (查询n次)
  • iterator查询,迭代数据的时候,只有用到数据的时候,才会查找数据库(懒加载)

3、区别

  • 查询数据方式不同: 查询全部与查询N+1
  • 一级缓存
    List查询,查询的结果会放入一级缓存,但不会从一级缓存中获取;
    Iteraotro查询,会放入一级缓存,同时也会从一级缓存中获取。

10、lazy 属性

1、懒加载

  • 用到数据的时候,才向数据库发送查询的sql;

2、懒加载异常(org.hibernate.LazyInitializationException: could not initialize proxy - no Session)

  • 在关闭后,不能能懒加载数据, 那么就要求关闭前把懒加载使用的数据先查询出来:

      Session session = sf.openSession();
      session.beginTransaction();
      
      // 懒加载
      Employee emp = (Employee) session.load(Employee.class, 1);  
      /*
       * 解决懒加载异常:
       *     Session关闭后,不能使用懒加载数据!
       *     (1) 在session关闭之前,先使用一次数据; 那么session关闭后再使用对象数据,就不是懒加载数据了
       *     (2) 强迫代理对象初始化
       * */
      //emp.getName();            // select ... 
      Hibernate.initialize(emp);
      
      session.getTransaction().commit();
      session.close();
    
      System.out.println(emp.getName());     // 不是懒加载数据, 因为数据已经查询出来啦
    

11、关系映射

1、集合

  • set/list/map

    
    
    
    
      
          
              
          
          
          
          
          
              
              
          
          
          
          
              
              
              
          
          
          
          
              
              
              
          
          
      
      
    
    
  • 多对一

    public class Address {
    
      private int id;
      private String name;
      private String shortName;
      private String code;
    
      // 地址与用户, 是多对一的关系
      private Users user;
    …
    }
    
    
      
    
      
      
          
              
              
                  
              
              
              
              
              
              
               
                      
          
          
      
    
  • 一对多

    public class Users {
    
     private int id;
     private String name;
      private int age;
      // 用户与地址,是一对多的关系  【注意一定要用接口接收!】
      private Set
    address = new HashSet
    (); }
  • Inverse属性

    
      
    
      
          
              
              
                  
              
              
              
              
               
                  
                  
               
              
          
          
    
      
    
  • 多对多

    
      
    
      
          
              
              
                  
              
              
              
              
               
                  
                  
               
              
          
          
      
    
    
      
    
      
          
              
              
                  
              
              
              
              
               
                  
                  
               
               
          
          
    
      
    
  • 一对一

    
          
              
              
                  
                  
                      idCard
                  
              
              
              
              
              
                      
          
          
    
      
    
     
          
              
              
                  
              
              
              
              
              
              
          
          
    
      
    
  • 组件映射

    
    
      
          
      
      
      
      
      
          
          
      
    
    
    
    
  • 继承映射

    
    
    
      
          
      
      
      
      
      
      
      
      
      
          
      
      
      
      
      
          
      
      
      
    
    
        
      
          
              
                  
              
              
              
              
              
              
                  
                  
              
              
              
              
                  
                  
              
              
              
          
      
    
      
      
          
              
                  
              
              
              
              
              
              
              
                   
              
              
              
              
                  
              
          
          
      
    
  • hql

    
          
              
              
                  
              
              
              
              
               
                  
                  
               
              
          
          
          
          
              
              
              
              
          
    
      
    
      Session session = sf.openSession();
      session.beginTransaction();
    
      // 从配置文件中,读取hql,便于后期维护
      Query q = session.getNamedQuery("my_hql_select");
      //q.setParameter("name_", name);
      
      session.getTransaction().commit();
      session.close();
    

12、二级缓存

1、特点

  • 基于应用程序的缓存、基于sessionFactory级别的缓存;
  • 缓存数据可以被多个session共享,但需要指定哪些对象要放入二级缓存中;
  • 放入二级缓存中对象的特点:经常使用、不会被经常修改。

2、步骤

  • hibernate.cfg.xml中配置

      开启二级缓存 
     true
     指定使用哪一种二级缓存 
     org.hibernate.cache.HashtableCacheProvider
      开启查询缓存 
     true
      加入二级缓存的类 
     
     
      集合缓存 (集合缓存,集合元素也要放入二级缓存)
     
    

3、缓存策略

  • usage="read-write" 二级缓存的数据可以读、写
  • usage="read-only" 二级缓存的数据只读
  • usage="nonstrict-read-write" 非严格读取
  • usage="transactional" 基于事务的策略

4、hql 查询缓存

    Dept dept = null;
    /*
     * Session1:
     */
    Session session1 = sf.openSession();
    session1.beginTransaction();
    // hql 查询
    Query q = session1.createQuery("from Dept").setCacheable(true);// 放入二级缓存或者从二级缓存中获取
    q.list();
    session1.getTransaction().commit(); 
    session1.close();
    
    System.out.println("===============================");
    /*
     * Session2:        
     */
    Session session2 = sf.openSession();
    session2.beginTransaction();
    // hql 查询
    q = session2.createQuery("from Dept").setCacheable(true); // 放入二级缓存或者从二级缓存中获取
    q.list();
    session2.getTransaction().commit();  
    session2.close();

5、 更新数据

  • 不会通知一级缓存,会通知二级缓存;

13、连接池

1、Hibernate对连接的支持

  • 查看hibernate.properties,hibernate.connection.pool_size 1,hibernate自带的连接池,只有一个连接

2、hibernate对C3p0连接池的支持

     
     org.hibernate.connection.C3P0ConnectionProvider
     
     6
     
     4
     
     2
     
     100
     
     3000  

14、创建Session的两种方式

1、方式1

  • 每次都创建一个新的session
    Session session1 = sf.openSession();
    Session session2 = sf.openSession();
    System.out.println(session1 == session2);  // false

2、方式2

  • 线程的方式创建session

       
       thread
    
      Session session3 = sf.getCurrentSession();
      Session session4 = sf.getCurrentSession();
      System.out.println(session3 == session4);  // true
    

你可能感兴趣的:(Hibernate小结)