初识Hibernate

       前言

        Hibernate是数据持久化工具,也是一个开放源代码的ORM解决方案。内部封装了通过JDBC访问数据库的操作,向上层应用提供面向对象的数据访问API。基于ORM,Hibernate在对象模型和关系型数据库的表之间建立了一座桥梁,通过Hibernate,程序员不需要使用SQL语句操作数据库的表,使用API直接操作JavaBean对象就可以实现数据的增、删、改、查。显著降低由于对象与关系数据库在数据表现方面的范例不匹配导致的开发成本


Hibernate框架的优缺点

优点:

  1. Hibernate功能强大,是Java应用于关系数据库间的桥梁,较之JDBC方式操作数据库,代码量大大减少,提高开发速度,降低维护成本。
  2. Hibernate支持许多面向对象的特性,组合、继承、多态等。使开发人员不必再面向对象领域的对象模型和面向数据库的关系数据库直接来回切换,方便开发人员进行领域驱动的面向对象的设计与开发。
  3. 可移植性好。系统不会绑定在某个特定的关系型数据库上,对于系统更换数据库,只需要修改Hibernate配置文件即可正常运行。

缺点:

  1. 不适合以数据为中心大量使用存储过程的应用。
  2. 大规模的批量插入、修改、删除不适合Hibernate。

Hibernate与MyBatis比较

        Hibernate与MyBatis都属于ORM框架,为数据层提供持久化操作的支持。

  1. 相对于MyBatis的”SQL-Mapping”的ORM实现,Hibernate的ORM实现更加完善,提供对象状态管理的功能。Hibernate对数据操作,针对的是Java对象,即使用Hibernate的查询语言HQL,书写规则也是面向对象的。
  2. Hibernate与具体数据库的关联只需要在XML中配置即可,Hibernate开发者不需要关注SQL的生成与结果的映射,所有的HQL语句与具体使用的数据库无关,便于修改、移植性好。MyBatis直接使用SQL语句,不同数据库可能会有差异、修改工作量大、可移植性差。
  3. 由于直接使用SQL语句、MyBatis灵活性更高、Hibernate对于关系型模型设计不合理、不规范的系统不适用。不考虑缓存的情况下,MyBatis执行效率比Hibernate高一些。

Hibernate环境搭建
  1. 下载需要的JAR文件
    hibernate-core
    antlr
    commons-collections
    dom4j
    javassist
    jta
    slf4j-api
    hibernate-jpa
  2. 部署JAR文件
  3. 创建Hibernate配置文件hibernate.cfg.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
        <hibernate-configuration>
            <session-factory>
                <!--数据库URL-->
                <property name="connection.url">
                    jdbc:oracle:thin:@10.0.0.176:1521:orcl
                </property>
                <!--数据库用户-->
                <property name="configuration.username">scott</property>
                <!--数据库密码-->
                <property name="configuration.password">tiger</property>
                <!--数据库JDBC驱动-->
                <property name="configuration.driver_class">
                    oracle.jdbc.driver.OraleDriver
                </property>
                <!--每个数据库都有其对应的防御以匹配其平台特性-->
                <property name="dialect">
                    org.hibernate.dialect.Oracle10gDialect
                </property>
                <!--指定当前session范围和上下文-->
                <property name="current_session_context_class">thread</property>
                <!--是否运行期生成的SQL输出到日志以供调试-->
                <property name="show_sql">true</property>
                <!--是否格式化SQL-->
                <property name="format_sql">true</property>
            </session-factory>
        </hibernate-configuration>
  4. 创建持久化类和映射文件

       持久化类指其实例化状态需要被Hibernate持久化到数据库中的类。在应用的设计中,持久化类通常对应需求中的业务类实体。Hibernate对持久化类的要求很少,它鼓励采用POJO编程模型来实现持久化类。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    <hibernate-mapping>
        <class name="cn.hibernatedemo.entity.Dept" table="`DEPT`">
            <id name="deptNo" type="java.lang.Byte" column="`DEPTNO`">
                <generator class="assigned"/>
            </id>
            <property name="deptName" type="java.lang.String" column="`DNAME`"/>
            <property name="location" type="java.lang.String">
                <column name="`LOC`"></column>
            </property>
        </class>
    </hibernate-mapping>

使用Hibernate完成持久化操作
  1. 读取并解析配置文件及映射文件

    Configuration conf =new Configuration().configure();

    根据默认位置Hibernate配置文件中的信息,构建Configuration对象。

  2. 依据配置文件和映射文件中的信息,创建SessionFactory对象。

    SessionFactory sf=conf.buildSessionFactory();

Configuration对象会根据当前数据库配置信息,构造SessionFactory对象。一旦构造完成,Configuration对象的任何变更将不会影响已经创建的SessionFactory对象。如果Hibernate配置信息有改动,那么需要基于改动后的Configuration对象重新构造一个SessionFactory对象。

  • 打开Session。

    Session session = sf.getCurrentSession();

SessionFactory负责创建Session对象。Session是Hibernate持久化操作的基础。Session作为贯穿Hibernate的持久化管理器的核心,提供了众多方法。save()、delete()、update()、get()、load()等。

  • 开始一个事务。

    Transaction tx = session.beginTransaction();
  • 数据库操作。

    session.save(user);
  • 结束事务

    tx.commit();或tx.rollback();
  • 如果通过SessionFactory的openSession()获取的Session对象需要关闭session。

    session.close();

Hibernate中Java对象的三种状态
  1. Java对象的三种状态

           当应用通过调用Hibernate API与框架进行交互时,需要从持久化的角度关注应用对象的生命周期。持久化生命周期时Hibernate中的一个关键概念,正确理解生命周期,可以更好了解Hibernate的实现原理。

    • 瞬时状态(Transient)

      瞬时状态又称临时状态。Java对象与数据库中的数据没有任何的关联,即此Java对象在数据库中没有相关联的记录。此时Java对象的状态为瞬时状态。Session对于瞬时状态的Java对象是一无所知的,当对象不再被其他对象引用时,它的所有数据也就丢失了,对象将会被Java虚拟机按照垃圾回收机制处理。
    • 持久状态(Persistent)

      当对象与Session关联,被Session管理时,他就处于持久状态。处于持久状态的对象拥有数据库标识(数据库中的主键值)。对象什么时候与Session发生关联?(1)通过Session的查询接口,或者get()、load()从数据库中加载对象的时候,加载对象是与数据库表中的一条记录关联、此时对象与加载它的Session发生关联。(2)对瞬时状态的对象调用Session的save()、saveOrUpdate()等方法、在保存对象数据的同时,Java对象的内部状态发生了任何变更,Hibernate会选择合适的时机将变更同步到数据库中。
    • 游离状态(Detached)

      游离状态又称脱管状态。处于持久状态的对象,脱离与其关联的Session管理后,对象处于游离状态。处于游离状态的对象,Hibernate无法保证对象所包含的数据与数据库中的记录一致。因为Hibernate已经无法感知该对象的任何操作。Session提供了update()、saveOrUpdate()等方法。将处于游离状态的对象数据以更新的方式同步到数据库中,并将该对象与当前的Session关联。这时,对象的状态从游离状态转换为持久状态。

2.三种状态之间的转换

  1. 瞬时状态转为持久状态

    使用Session的save()、saveOrUpdate()方法等保存对象后,该对象的状态由瞬时状态转为持久状态

    使用Session的get()、load()方法获取对象,该对象的状态是持久状态

  2. 持久状态转为瞬时状态

    执行Session的delete()对象由原来的持久状态转变为瞬时状态,因为此时该对象没有与任何数据库数据关联

  3. 持久状态转为游离状态

    执行Session的evict()、clear()、close(),对象由原来的持久状态转为游离状态

  4. 游离状态转为持久状态

    执行Session的update()或saveOrUpdate(),对象由游离状态转为持久状态。

  5. 游离状态转为瞬时状态

    执行Session的delete()方法,对象由游离状态转为瞬时状态


脏检查及刷新缓存机制

       Session是Hibernate向应用程序提供的持久化操纵的主要接口,提供了基本的保存、更新、删除、加载Java对象的方法。Session具有一个缓存,可以管理和跟踪所有持久化对象。在某些时间点,Session会根据缓存中对象的变化来执行相关SQL语句,将对象发生的变化同步到数据库中,就是将数据库同步为域Session缓存一致。称为刷新缓存

  1. 脏检查

    在Hibernate中,数据前后发生变化的对象,称为脏对象。

    tx=session.beginTransaction();
    //获取部门对象,dept处于持久状态
    Dept dept=(Dept)session.load(Dept.class,new Byte("11"));
    //修改后,部门信息和之前不同,此时dept对象为脏对象
    dept.setDname("质量部");
    //提交事务
    tx.commit();
  2. 刷新缓存机制

    需要注意,当Session缓存中对象的属性发生变化时,Session并不会立即执行脏检查和执行相关联的SQL语句,而是在特定的时间点,即刷新缓存时才执行。这使得Session能够把多次变化合并为一条或者一批SQL语句,减少访问数据库次数,从而提高应用程序的数据访问性能。

    默认情况Session会在以下时间点刷新缓存

    1.应用程序显示调用Session的flush(),进行刷新缓存操作,触发脏检查,视情况执行相关的SQL语句。
    2.应用程序调用Transaction的commit(),commit()会先调用Session的刷新缓存方法flush(),然后向数据库提交事务。

更新数据的方法

       Hibernate中的Session提供了多种更新数据的方法:update()、saveOrUpdate()、merge()

  1. update(),用于将游离状态的对象恢复为持久状态,同时进行数据库更新操作。参数对象的OID为null时会报异常。
  2. saveOrUpdate(),同时包含save()与update(),如果入参时瞬时状态对象就调用save(),如果是游离状态的对象就调用update()
  3. merge(),能把作为参数传入的游离状态对象的属性复制到一个拥有相同OID的持久状态对象中,通过对持久状态对象的脏检查实现实现更新操作,返回该持久状态对象;如果无法从Session缓存或数据库中加载到相应的持久状态对象,即传入的时瞬时状态对象,则创建其副本执行插入操作,并返回这一新的持久状态对象。