Hibernate学习笔记

Hibernate

1、概述

1.1 EE三层结构

在这里插入图片描述

1.2 各层对应技术

在这里插入图片描述

2、使用

2.1 导入jar包

  • 数据库驱动包
  • Hibernate开发必需的jar包(required)
  • Hibernate引入日志记录包(log4j)

2.2 创建映射

  • 数据库表属性与实体类映射体现在 hibernate 中是配置文件
  • 配置文件的命名原则上是随意的,但一般遵循一定的规则,即 类名.hbm.xml
  • 文件在类所在目录下。

2.3 创建核心配置文件

  • 核心配置文件的名称遵循的规则是 hibernate.cfg.xml
  • 配置文件在项目中的位置与映射文件不同,在根目录下。

2.4 使用

  • 加载 Hibernate核心配置文件

  • 创建一个 SessionFactory 对象(类似于 JDBC 中的连接池);

  • 通过 SessionFactory 对象获取到 Session 对象(类似于 JDBC 中的 Connection );

  • 手动开启 事务

  • 编写处理代码(操作数据库代码);

  • 事务提交;

  • 资源释放。

3、Hibernate的常用配置

3.1 XML提示的配置

  • 配置本地 dtd 文件,在开发计算机未连接网络时仍然有提示功能。

3.2 Hibernate映射的配置

3.2.1 class标签的配置
  • 该标签用来建立类与数据库表的映射关系;
  • 属性
    • name : 类的全路径
    • table : 表名 (类名与表名一致,可省略)
    • catlog : 数据库名 (一般省略)
3.2.2 id标签的配置
  • 该标签用来建立类中的属性和表中主键之间的关系;
  • 属性
    • name : 类中的属性名
    • colume : 表中的字段名 (类名与字段名一致,可省略)
    • length : 长度 (自动建表时使用)
    • type : 数据类型 (自动建表时使用)
3.2.3 property标签的配置
  • 该标签用来建立类中的属性和表中普通属性之间的关系;
  • 属性
    • name :
    • colume :
    • length :
    • type :
    • not-null : 设置非空
    • unique : 设置唯一

3.3 Hibernate核心的配置

3.3.1 必须的配置
  • 连接数据库的基本参数
    • 驱动类
      • hibernate.connection.driver_class
      • com.mysql.cj.jdbc.Driver
    • 数据库名称(URL路径)
      • hibernate.connection.url
      • jdbc:mysql:///test
    • 用户名
    • 密码
  • 方言
    • hibernate.dialect
    • org.hibernate.dialect.MySQLDialect
3.3.2 可选的配置
  • 显示(输出)SQL语句
    • hibernate.show_sql
    • true
  • 格式化SQL语句
    • hibernate.format_sql
    • true
  • 自动建表
    • hibernate.hbm2ddl.auto
    • 取值
      • none 不使用hibernate的自动建表
      • create 有表则删除后创建,无表直接创建(用于测试)
      • create-drop 有表则删除并创建,执行操作后删除表;无表则创建,执行完后删除(用于测试)
      • update 有表则使用表(可能会更新表结构),无表则创建表
      • validate 只会使用现有的表(没有不会创建),但会校验映射和表结构。
3.3.3 映射文件的引入
  • mapping标签
    • resource
      • hibernate/Customer.hbm.xml(文件路径)

4、Hibernate的核心API

4.1 Configuration

  • Hibernate 的配置对象,并启动之,随后创建 SessionFactory 对象;
  • 作用
    • 加载核心配置文件(hibernate.cfg.xml)
    • 手动加载映射文件(当核心配置文件中未加载时)

4.2 SessionFactory

  • 初始化 Hibernate,并创建 Session 对象;
  • 内部维护了 Hibernate 的连接池和二级缓存(可以自己配置C3P0连接池<在核心配置文件中>);
  • 是线程安全的;
  • 一个项目创建一个对象即可(非轻量级的);
    • 可以抽取一个工具类

4.3 Session

  • 类似 JDBC 中的 Connection 对象;

  • 非线程安全的(定义时不能定义为全局变量,在使用到的方法中定义);

  • API

    • 保存方法

      • // 返回保存在数据库中的id
        Serializable save(Object obj);
        
    • 查询方法

      • // 1. 采用 立即 加载
        // 2. 返回的是 真实对象 本身
        // 3. 查询找不到的对象时返回 null
        T get(Class c, Serializable id);
        
      • // 1. 采用 延迟 加载(lazy加载)
        // 2. 返回的是 代理对象(利用javassist技术产生的代理)
        // 3. 查询找不到的对象时 报错(ObjectNotFoundException)
        T load(Class c, Serializable id);
        
    • 修改方法

      • // 建议 先查询,后修改
        void update(Object obj);
        
    • 删除方法

      • // 建议 先查询,后删除(级联删除)
        void delete(Object obj);
        
    • 保存或修改

      • // 操作对象表中没有,则保存;否则修改
        void saveOrUpdate(Object obj);
        
    • 查询所有

      • 使用 HQL

        • Hibernate Query Language

        • Query query = session.createQuery("from Customer");
          List<Customer> list = query.list();
          for (Customer customer : list) {
              System.out.println(customer);
          }
          
    • 使用 SQL

      • SQLQuery query = session.createSQLQuery("select * from cst_customer");
        List<Object[]> list = query.list();
        for(Object[] objects : list) {
            System.out.println(Arrays.toString(objects));
        }
        

4.4 Transaction

  • Hibernate 中管理事务的对象;
  • 方法
    • commit();
    • rollback();

5、持久化类的编写规则

5.1 持久化类

  • 一个Java类拥有一个与它形成映射的数据库表,这样的类在Hibernate中被称为持久化类。
    • 持久化类 = Java类 + 映射文件

5.2 持久化类的编写规则

  • 持久化类提供一个无参数的构造方法

    • Hibernate 底层需要使用反射来生成实例对象(如查询方法get的第一个参数)。
  • 属性需要私有,并给这些属性getset方法

    • Hibernate中需要获取这些属性值,并设置对象的值。
  • 持久化类需要一个唯一标识OID与数据库表主键对应

    • Java中通过对象的地址区分是否是同一个对象,数据库中通过表中的主键区分是否是同一条记录,Hibernate中通过持久化类的OID属性区分是否是一个对象。
  • 持久化类中的属性尽量使用包装类类型

    • 基本数据类型的默认值是0, 0有很多的歧义。
  • 持久化类不能使用final关键字进行修饰

    • Hibernate中有延迟加载技术,具体的是调用某方法会返回一个代理对象(对没有实现接口的类),这里又用到了底层技术——字节码增强技术,即使用了继承机制,被final关键字修饰的类是不能被继承的。

6、主键生成策略

6.1 主键的分类

  • 自然主键
    • 主键本身就是表中应有的一个字段(是实体中的一个必须属性)
      • 如创建一个人员表,使用人的身份证号作为主键。
  • 代理主键
    • 主键本身不是表中的一个必须字段(不是实体中的某个具体属性)
      • 如创建一个人员表,不使用身份证号,而用了一个与此表不相关的字段ID(PNO)。
  • 一般使用代理主键
    • 避免后期修改源代码
      • OCP原则:对程序的扩展是open的,对源代码的修改是close的。

6.2 主键生成策略

  • increment
    • 适用于 shortintlong类型的主键;
    • Hibernate中的自动增长机制;
    • 一般在单线程程序中使用。
      • 在使用前会发送一条语句 select max(id) from table,之后让id加一,故存在线程安全问题。
  • identity
    • 适用于 short, int, long类型的主键;
    • 使用数据库底层增长机制,故需要带有自增机制的数据库支持(如MySQL)。
  • sequence
    • 适用于short, int, long类型的主键;
    • 使用序列方法,需要支持序列方式的数据库(如Oracle)。
  • native
    • 本地策略,可以在 identitysequence 之间自动切换。
  • uuid
    • 适用于字符串类型的主键。

7、持久化类的三种状态

  • 为了更好的管理持久化类,将持久化类分成三个状态。

  • // 三种状态的区分
    Session session = HibernateUtils.openSession();
    Transaction transaction = session.beginTransaction();
    
    // 瞬时态对象
    Customer customer = new Customer();
    customer.setCust_name("zhangsan");
    // 持久态对象
    Serializable id = session.save(customer);
    
    transaction.commit();
    session.close();
    
    // 脱管态对象
    System.out.println(customer);
    

7.1 瞬时态(transient)

  • 亦称 临时态自由态
  • 可以由 new 关键字创建;
  • 没有唯一标识 OID,不受 Session 管理。

7.2 持久态(persistent)

  • 有唯一标识 OID,被 Session 管理;
  • 会自动更新数据库;
    • 底层原理 Hibernate 提供的一级缓存快照 技术。
  • 可以通过 get(),load(),find(),iterate() 获得。

7.3 脱管态(detached)

  • 亦称离线态游离态
  • 有唯一标识 OID,没有被 Session 管理;
  • 可以由 持久态 对象通过 close(), clear(), evict() 转换得到。

8、Hibernate的一级缓存

  • Hibernate 中提供了一些优化手段,如 缓存 技术和 快照 技术;
  • Hibernate一级缓存 又称为 Session缓存,其生命周期与 Session 一致;
  • 一级缓存 由一系列 Java 集合构成;
  • Hibernate 快照区的存在是为了使一级缓存和数据库表中的数据保持一致。
    • Hibernate一级缓存中存入数据时,会拷贝一份到快照区
    • 并在执行commit()方法时
      • 会清理一级缓存中的数据(执行flush())操作;
      • 同时会检测一级缓存中的数据是否和快照区中的数据一致。
        • 不一致时会执行update()方法,将一级缓存中的数据存入到数据库中,并更新快照区(这也是持久态对象会自动更新数据库的原因)。

9、Hibernate的事务管理

  • 事务
    • 逻辑上的一组操作,并且组成这组操作的各个逻辑单元,必须同时成功或失败。

9.1 事务特性

  • 原子性
    • 代表事务不可分割
  • 一致性
    • 代表事务执行的前后,数据的完整性保持一致
  • 隔离性
    • 代表一个事务执行过程中,不应受到其他事务的干扰;
    • 不考虑隔离性,会引发一系列安全问题
      • 读问题
        • 脏读
          • 一个事务读到另一个事务未提交的数据。
        • 不可重复读
          • 一个事务读到另一个事务已经提交的update数据,导致查询不一致。
        • 虚读
          • 一个事务读到另一个事务已经提交的insert数据,导致查询不一致。
      • 写问题
        • 引发两类丢失更新
  • 持久性
    • 代表事务执行完成后,数据持久到数据库中

9.2 读问题的解决

可以通过设置事务隔离级别解决。

  • Read uncommitted
    • 三类读问题都会发生。
  • Read committed
    • 解决脏读;
    • Oracle支持。
  • Repeatable read
    • 解决脏读和不可重复读;
    • MySQL支持。
  • Serializable
    • 解决所有。

9.3 Hibernate中事务隔离级别的设置

<!--在核心配置文件中设置事务的隔离级别-->
<!--
	1--Read uncommitted
	2--Read committed
	4--Repeatable read
	8--Serializable
-->

<property name='hibernate.connection.isolation'>4</property>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值