• ★★★ 掌握(能写能默)
  • ★★ 理解(能讲能说)
  • ★ 了解(知道即可)

理解数据持久化概念和Hibernate 的作用 ★★

持久化:

  • 持久化是程序数据在 瞬时状态 和 持久状态 间转换的过程常用持久化技术包括(序列化、数据库技术)

数据库连接技术JDBC存在的缺点:★★

  • 重复性工作多、代码冗余、开发效率低、代码移植困难

关于Hibernate ★★

定义:

  • 优秀的Java 持久化层解决方案

作用:

  • 主流的ORM(对象-关系映射)工具
  • 简化了JDBC 繁琐的编码

关于ORM ★★

Object Relational Mapping 对象-关系映射

  • 编写程序的时候,以面向对象的方式处理数据
  • 保存数据的时候,却以关系型数据库的方式存储
  • 所以,为了降低开发难度,可以利用ORM实现即可实现自动转换

ORM解决方案 ★★

  • 包含 4个部分:
    1. 对持久化对象提供一种查询语言或者API
    2. 在持久化对象上执行基本的增、删、改、查操作
    3. 对象关系映射工具
    4. 提供与事务对象交互、执行检查、延迟加载以及其他优化功能

Hibernate 框架的优缺点及适用场合 ★★

优点:

  1. 可以随心所欲的使用 对象编程思维 来操纵数据库;
  2. 支持各种关系数据库;
  3. 从一对一到多对多的各种复杂关系,不存在数据库兼容性问题。

缺点:

  • 限制您所使用的对象模型。 (例如,一个持久性类不能映射到多个表)。

使用场合:

  • Hibernate可以应用在任何使用JDBC的场合

使用Hibernate 实现数据持久化操作 7步骤 ★★★

// 第一步:读取配置Configuration
Configuration cfg = new Configuration().configure();
// 第二步:创建sessionFactory
SessionFactory factory = cfg.buildSessionFactory();
// 第三步:打开session
Session session = factory.openSession();
// 第四步:开启事务Transaction
Transaction tran = session.beginTransaction();
// 第五步:进行持久化的增\删\改\查(CRUD)操作
session.save()/update()/delete()/get();
// 第六步:提交事务
tran.commit();
// 第七步:关闭资源(即关闭session)
session.close();

编写Hibernate 配置文件hibernate.cfg.xml ★★★

<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- 连接数据库的基本配置 -->
<property name="hibernate.connection.driver_class">oracle.jdbc.OracleDriver</property>
<property name="hibernate.connection.url">jdbc:oracle:thin:@127.0.0.1:1521:orcl</property>
<property name="hibernate.connection.username">house</property>
<property name="hibernate.connection.password">house</property>

<!-- 数据库方言() -->
<property name="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>

<!-- 在主配置文件中注册hbm映射文件 -->
<mapping resource="com/njzb/myhouse/po/Users.hbm.xml"/> 
</session-factory>
</hibernate-configuration>

将持久化类映射到数据库表 ★★★

例如:Users.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 对象模型 与 关系模型的映射 -->
<hibernate-mapping package="com.myhouse.pojo">
<!-- 使用<class>元素定义 房源类House 和 房源表TBL_HOUSE 的映射 -->
<class name="House" table="TBL_HOUSE" >
<!-- 使用<id>元素定义用户类唯一标识属性OID 和 用户表主键字段的映射-->
<id name="id" column="ID" type="integer">
<!-- 使用<generator>元素生成用户的主键策略
例如:使用序列自动维护主键Primary Key
-->
<generator class="sequence">
<param name="sequence">SEQ_HOUSE</param>
</generator>
</id>
<!-- 使用<property>元素定义 类属性 和 表字段 的映射 -->
<property name="title" column="TITLE" type="string"/>
<property name="area" column="AREA" type="double"/>
<property name="desc" column="DESCRIPTIONS" type="string"/>
<property name="price" column="PRICE" type="double"/>
<property name="userId" column="USER_ID" type="string"/>
<property name="typeId" column="TYPE_ID" type="integer"/>
<property name="streetId" column="STREET_ID" type="integer"/>
</class>
</hibernate-mapping>

使用<class>元素的schema 属性设置数据库的Schema ★

例如:`<class name=”com.myhouse.pojo.House” table=”TBL_HOUSE” schema=”HOUSE”>`在Oracle数据库,schema就是指用户名,只有 HOUSE 用户才可以操作 TBL_HOUSE 这张表

管理Session 三态 ★★

临时状态(Transient) ★

  1. 由new操作符创建,且尚未与`Hibernate Session`关联的对象被认定为临时(Transient)的。
  2. 临时(Transient)对象不会被持久化到数据库中,也不会被赋予持久化标识(identifier)。
  3. 如果临时(Transient)对象在程序中没有被引用,它会被垃圾回收器(garbage collector)销毁。
  4. 使用Hibernate Session可以将其变为持久(Persistent)状态。
    • (Hibernate会自动执行必要的SQL语句)

持久(Persistent) ★

  1. 持久的实例在数据库中有对应的记录,并拥有一个持久化标识(identifier)。
  2. 持久(Persistent)的实例可能是刚被保存的,或刚被加载的,无论哪一种,按定义,它存在于相关联的Session作用范围内。
  3. Hibernate会检测到处于持久状态的对象的任何改动,在当前操作单元(unit of work)执行完毕时,将对象数据与数据库同步(synchronize),开发者不需要手动执行UPDATE。将对象从持久(Persistent)状态变成瞬时(Transient)状态,也不需要手动执行DELETE语句。

游离(Detached) ★

  1. 与持久(Persistent)对象关联的Session被关闭后,对象就变为游离(Detached)的。
  2. 对游离(Detached)对象的引用依然有效,对象可继续被修改。
  3. 游离(Detached)对象如果重新关联到某个新的Session上,会再次转变为持久(Persistent)的(在Detached其间的改动将被持久化到数据库)。这个功能使得一种编程模型,即中间会给用户思考时间(user think-time)的长时间运行的操作单元(unit of work)的编程模型成为可能。我们称之为应用程序事务,即从用户观点看是一个操作单元(unit of work)。

Session三态的总结:★★ (具体详见 三态转换图)

其实可以把session看做是三种状态的分水岭

  1. 新new出来的java实体对象是瞬态的,此时数据库中并没有数据与之对应。
  2. 当使用session.save(new出来的实体对象)方法时,这时对象已经被session管理,变成了持久状态了。
  3. 此时已经有一条数据与之对应了,在session提交关闭前,这个持久态对象的属性如果发生变化会被session检查到的,它会发出一条update语句把对象的改变同步到数据库中。
  4. session提交关闭之后,对象就从持久态变成了游离态了。
  5. 当使用 session.load() 或 session.get() 方法时,游离态的对象又会变成持久态。

脏检查:★

当一个 `Users` 对象被加入到 `Session` 缓存中时,`Session` 会为 `Users` 对象的值类型的属性复制一份快照。当 `Session` 清理缓存时,会先进行脏检查,即比较 `Users` 对象的当前属性与它的快照;判断 `Users` 对象的属性是否发生了变化,如果发生了变化,就称这个对象是“脏对象”,`Session` 会根据 脏对象 的最新属性来执行相关的SQL语句,从而同步更新数据库

缓存清理机制:★

当Session缓存中对象的属性每次发生了变化,Session并不会立即清理缓存和执行相关的SQL Update语句,而是在特定的时间点才清理缓存,这使得Session能够把几条相关的SQL语句合并为一条SQL语句,减少访问数据库的次数,从而提高应用程序的数据访问性能

在默认情况下,Session会在以下时间点清理缓存。 ★

  1. 当应用程序 调用org.hibernate.Transaction的commit()方法的时候.commit方法先清理缓存,然后再向数据库提交事务。Hibernate之所以把清理缓存的时间点安排在事务快结束时,一方面是因为可以减少访问数据库的频率,还有一方面是因为可以尽可能缩短当前事务对数据库中相关资源的锁定时间。
  2. 当应用程序执行一些查询操作时,如果缓存中持久化对象的属性已经发生了变化,就会清理缓存,使得Session缓存与数据库已经进行了同步,从而保证查询结果返回的是正确的数据。
  3. 当应用程序显示调用Session的flush()方法的时候。

get()和load()方法的用法和区别 ★

load()方法:

  • 常规情况下,仅提供给Hibernate底层源码使用
  • load方法认为该数据在数据库中一定存在,可以放心的使用代理来延迟加载,如果在使用过程中发现了问题,就抛ObjectNotFoundException异常;

get()方法:

  • 用法示例:
    • Users user = (Users)session.get(Users.class, userId);
    • 首先在session缓存中查找
    • 然后在二级缓存中查找
    • 还没有就查数据库
    • 数据库中没有就返回null

几种更新数据方法的作用及区别 ★★

save()方法:

用于将一个临时对象转变为持久化对象,也就是将一个新的业务实体保存到数据库中.

update()方法:

用于将一个游离对象重新转变为持久化对象,也就是更新一个已经存在的业务实体到数据库中;

saveOrUpdate():

saveOrUpdate是把我们提供的对象变成一个 持久状态 的对象;兼具了save()和update()方法的功能,该方法根据传入参数的状态执行不同的操作,当为临时状态时,调用save()方法;当为持久化状态时,则直接返回;当为游离状态时,调用update()方法。

merge()方法:

merge方法是把我们提供的对象转变为 游离状态 的对象;主要用于更新和保存实体,当实体不存在是,则执行保存操作,当实体已经存在时,执行更新操作,其实同saveOrUpdate()的功能是类似的。

merge和saveOrUpdate方法区别在于:

  1. saveOrUpdate后的对象会纳入session的管理,对象的状态会跟数据库同步,再次查询该对象会直接从session中取;
  2. merge后的对象不会纳入session的管理,再次查询该对象还是会从数据库中取。

知识拓展:

一级缓存:

一级缓存就是Session级别的缓存,一个Session做了一个查询操作,它会把这个操作的结果放在一级缓存中,如果短时间内这个session(一定要同一个session)又做了同一个操作,那么hibernate直接从一级缓存中拿,而不会再去连数据库,取数据。

二级缓存:

二级缓存就是SessionFactory级别的缓存,顾名思义,就是查询的时候会把查询结果缓存到二级缓存中,如果同一个sessionFactory创建的某个session执行了相同的操作,hibernate就会从二级缓存中拿结果,而不会再去连接数据库。