0 回顾:

0.1 hibernate -> 操作数据库Dao

  1. 导包 - required/驱动包
  2. 准备数据库/实体类
  3. 配置文件

    1. 主配置文件 src/hibernate.cfg.xml

      1. property: project/etc/hibernate.properties

        • 5[数据库连接信息+方言] + 3[showformatauto]
        • 连接池
        • mapping - 引入ORM元数据
    2. ORM元数据配置 - 映射文件 - mapping

      • 类、表的映射关系

        <class name="" table>
              <id name column>
                  <genertor class="native">
              <property name>
  4. 使用

    1. 加载配置文件 Configuration configure()
    2. 获得 SessionFactory
    3. 获得 Session
    4. 开启事务 Transaction
    5. session.get/load/save/delete/update
    6. 关闭事务 commit/rollback
    7. 关闭资源 Session.close()

一、JavaBean规范:

  1. 属性私有化,提供get/set
  2. 提供无参构造器
  3. 基本数据类型建议使用包装类
  4. 必须有主键oid对应属性
  5. 不能用final修饰 -> CGlib代理

二、主键

2.1 主键种类

​ 代理主键:业务无关、对象无关,不能修改
​ 自然主键:表中存在非空并且唯一的字段,例如身份证号

2.2 主键生成策略

  • 主键生成策略 - 新增数据时,主键生成的方式
  • 代理主键:

    1. identity:数据库维护,自增长,不需要手动录入
    2. sequence:数据库维护,seq.nextVal 序列方式,需要指定参数[序列名],不需要手动录入
    3. increment:Hibernate维护,自增长,不需要录入

      • 在插入之前先查找ID最大值,+1插入hilo:自增长算法
    4. nativehilo + identity + sequence

      • 自动检测
    5. uuid:hibernate维护,id类型设置为varchar(32)
  • 自然主键:必须手动录入

    1. assigned

三、Hibernate对象状态

3.1 瞬时状态

  • 瞬时状态:对象没id,并且没有在session缓存中

3.2 持久化状态

  • 持久化状态:对象有id,并且在session缓存中

    • 内容发生修改,在事务提交时,都会同步到数据库中

3.3 游离/托管状态

  • 游离|托管状态:对象有id,没有不在session缓存中

    • session中对对象的操作,其实就是改变对象状态

四、session缓存与快照

4.1 session缓存

  • session缓存作用:为了提高查询效率

    • hibernate一级缓存
    @Test
    public void test01() {
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();
        // 5.Session操作数据库 增删改查
        // -----------------------
        Customer c1 = session.get(Customer.class, 7l);
        Customer c2 = session.get(Customer.class, 7l);
        Customer c3 = session.get(Customer.class, 7l);
        Customer c4 = session.get(Customer.class, 7l);
        Customer c5 = session.get(Customer.class, 7l);
        Customer c6 = session.get(Customer.class, 8l);
        // Session 是有缓存的
        System.out.println(c5 == c6);//true
        // -----------------------
        // 6.关闭事务
        tx.commit();
        // 7.关闭资源 
        session.close();
    }

4.2 session快照

  • session快照:为了节省不必要的update操作

    • 懒加载:load方法懒加载,lazy="true"
    • 结论:默认设置,就是最佳优化方案
    @Test
    public void test02() {
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();
        // -----------------------
        Customer c = session.get(Customer.class, 7l);
        c.setCust_name("阿里爸爸");
        c.setCust_name("阿里爸爸1");
        c.setCust_name("阿里爸爸2");
        c.setCust_name("阿里爸爸3");
        
        // 快照,节省不必要的操作,提高效率
        c.setCust_name("阿里妈妈");
        
        // -----------------------
        // 6.关闭事务
        tx.commit();
        // 7.关闭资源 
        session.close();
    }

Redis:缓存数据库,非关系型数据库

五、3种查询方式(重要)

5.1 HQL查询

  • HQL查询:Hibernate Query Language

    • 永远不会出现和表相关信息
    • 单表、简单的多表查询
    • session.createQuery(hql);
    @Test
    // 使用HQL查询全部Customer对象
    public void test01() {
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();
        // -----------------------
        // 1> 通过hql获得query对象
        // select * from cst_customer;
        // from Customer
        Query query = session.createQuery("from Customer");
        // 2> 获得查询集合列表
        List<Customer> list = query.list();
        
        System.out.println(list);
        // -----------------------
        tx.commit();
        session.close();
    }
//-----------------------------------------------------------------------------------
    @Test
    // 使用HQL根据name查询Customer对象
    public void test02() {
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();
        // -----------------------
        // 1> 通过hql获得query对象
        // select * from cst_customer;
        // from Customer where cust_name = ?
//        Query query = session.createQuery("from Customer where cust_id = ? and cust_name=?");
        //命名占位符
        Query query = session.createQuery("from Customer where cust_id=:id and cust_name=:name");
        // 2> 设置占位符参数
//        query.setString(0, "阿里巴巴");
//        query.setParameter(0, "阿里巴巴");
        // :id :name - 命名占位符
        query.setParameter("name", "阿里巴巴");
        query.setParameter("id", 8l);
        
        // 3> 获得结果集 - 唯一结果
        Customer c = (Customer) query.uniqueResult();
        
        System.out.println(c);
        // -----------------------
        tx.commit();
        session.close();
    }

5.2 Criteria查询

  • Criteria查询:单表条件查询

    • 只能做单表查询
    • session.createCriteria(Class);
    @Test
    // 使用Criteria查询全部Customer对象
    public void test01() {
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();
        // -----------------------
        // 1> 通过session获得Criteria对象
        Criteria criteria = session.createCriteria(Customer.class);
        
        // 2> 获得结果
        List<Customer> list = criteria.list();
        
        System.out.println(list);
        // -----------------------
        tx.commit();
        session.close();
    }

//-----------------------------------------------------------------------------------
    @Test
    // 使用Criteria根据name查询Customer对象
    public void test02() {
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();
        // -----------------------
        // 1> 获得criteira对象
        Criteria criteria = session.createCriteria(Customer.class);
        // 2> 设置查询条件 - 静态方法Restrictions
        criteria.add(Restrictions.eq("cust_name", "阿里巴巴"))
        .add(Restrictions.idEq(8l));
        
        // 3> 获得结果集 - 唯一结果
        Customer customer = (Customer) criteria.uniqueResult();
        System.out.println(customer);
        // -----------------------
        tx.commit();
        session.close();
    }

5.3 SQL查询

  • SQL查询

    • session.createSQLQuery(sql);

      • [Ljava.lang.Object;@2416a51,未addEntity(),输出的是这个,不是封装对象
    • addEntity(); -> 才能封装对象
    • list() -> 集合
    • uniqueResult() -> 单条记录
    @Test
    // 使用SQL查询全部Customer对象
    public void test01() {
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();
        // -----------------------
        // 0> sql语句
        String sql = "select * from cst_customer";
        // 1> 通过session获得SQLQuery对象
        SQLQuery sqlQuery = session.createSQLQuery(sql);
        
        // 2> 获得结果 - 所有的记录,每一条封装为一个数组
        List<Object[]> list = sqlQuery.list();
        
        for (Object[] os:list) {
            System.out.println(Arrays.toString(os));
        }
        
        // -----------------------
        tx.commit();
        session.close();
    }
//----------------------------------------------------------------------------------
    @Test
    // 使用SQL查询全部Customer对象 - 封装对象
    public void test03() {
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();
        // -----------------------
        // 0> sql语句
        String sql = "select * from cst_customer";
        
        // 1> 通过session获得SQLQuery对象
        SQLQuery sqlQuery = session.createSQLQuery(sql);
        // 在查询之前,添加实体类型
        sqlQuery.addEntity(Customer.class);
        
        // 2> 获得结果 - 按照实体类型,封装对象
        List<Customer> list = sqlQuery.list();
        System.out.println(list);
        // -----------------------
        tx.commit();
        session.close();
    }
//----------------------------------------------------------------------------------
    @Test
    // 使用sql根据name查询Customer对象
    public void test02() {
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();
        // -----------------------
        // 0> sql语句,占位符只能用?
        String sql = "select * from cst_customer where cust_name=?";
        // 1> 获得SQLQuery对象
        SQLQuery sqlQuery = session.createSQLQuery(sql);
        // 2> 设置查询条件 - 静态方法Restrictions
        sqlQuery.setParameter(0, "阿里巴巴");
        
        // 3> 获得结果集 - 唯一结果
        Customer customer = (Customer) sqlQuery.uniqueResult();
        System.out.println(customer);
        // -----------------------
        tx.commit();
        session.close();
    }

六、事务回顾

  • 事务:业务层面上,不能分割的最小单位

6.1 特点

  • 特点:

    • 原子性
    • 一致性
    • 持久性
    • 隔离性

6.2 并发问题

  • 并发问题:

    • 脏读:别人没提交的事务,被我读到了
    • 幻读:我刚删完的数据,别人又读出来了,感觉出现幻觉了
    • 不可重复读:第一次读的数据和第二次读的不一样
  • 隔离级别:

    • 读未提交。0001
    • 读已提交。0010
    • 可重复读。0100
    • 串行化。1000
  • mysql默认级别 isolution:4

    • hibernate可以设置隔离级别 - 主配置文件
        <!-- 设置隔离级别 -->
        <!-- #hibernate.connection.isolation 4 -->
        <property name="hibernate.connection.isolation">4</property>
        
        <!-- 配置session和当前线程绑定
            "current_session_context_class" thread
         -->
        <property name="current_session_context_class">thread</property>

6.3 误区

  1. 隔离级别设置
  2. session无需关闭
Last modification:August 29th, 2019 at 08:17 pm