[学习笔记] Hibernate之Hibernate入门

# 学习 # · 2021-03-12

Hibernate介绍及其环境搭建

1、Hibernate:是数据持久化工具,也是一个开放源代码的ORM解决方案。Hibernate在Java对象与关系数据库之间建立某种映射,以实现直接存取Java对象。

2、ORM概念:Objcet+Relative+Mapping,即对象关系映射,ORM关注是对象与数据库中的列的关系。

3、Hibernate的优点:

(1)简化了JDBC繁琐的编码。

(2)对面向对象特性支持良好。

(3)可移植性好。

4、Hibernate的缺点:

(1)不适合需要使用数据库的特定优化机制的情况。

(2)不适合大规模的批量数据处理。

5、Hibernate和MyBatis的比较:

(1)Hibernate是全自动,而MyBatis是半自动。

(2)Hibernate数据库移植性远大于MyBatis。

(3)Hibernate编码量小会减少开发周期,MyBatis编码量大会拖慢开发周期。

(4)SQL直接优化上,MyBatis(写在xml里)要比Hibernate(很多都是自动生成的)方便很多。

6、Hibernate环境搭建:

(1)使用IDEA创建Maven项目,在pom.xml配置文件中导入Hibernate依赖Jar包:

<!-- Hibernate 配置 -->
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>4.2.4.Final</version>
</dependency>

(2)由于特殊原因,Oracle依赖Jar包需要手动导入。操作参考:https://www.l5v.cn/archives/260/

(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:jdbc:oracle:thin:@数据库IP地址:端口号:数据库实例名 -->
        <property name="connection.url">jdbc:oracle:thin:@127.0.0.1:1521:orcl</property>
        <!--数据库用户 -->
        <property name="connection.username">scott</property>
        <!--数据库用户密码 -->
        <property name="connection.password">123456</property>
        <!--数据库JDBC驱动 -->
        <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
        <!--每个数据库都有其对应的Dialect以匹配其平台特性 -->
        <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)创建持久化类(Dept.java):

/**
 *  部门表对应的实体类
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Dept implements Serializable {
    // deptNo属性:用来唯一标识Dept类的每个实例
    // deptNo属性又称为id属性,也被称为对象标识符
    private Integer deptNo;
    private String deptName;
    private String loc;
}

(5)创建持久化类的映射文件(Dept.hbm.xml):

<?xml version="1.0"?>
<!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属性:表示持久化类的全限名
    ②table属性:表示持久化类对应的数据库表名
    -->
    <class name="com.aduo.pojo.Dept" table="`DEPT`" dynamic-update="true">
        <!--
        id元素:表示持久化类的OID和表的主键的映射
        ①name:表示持久化类属性的名称,和属性的访问器相匹配
        ②column:表示持久化类属性对应的数据库表字段名称,也可在子元素column中指定
        ③type:表示持久化类属性的类型
        -->
        <id name="deptNo" column="`DEPTNO`" type="java.lang.Integer">
            <!--
            generator元素:用于指定主键的生成策略。
            ①class属性:指定具体主键生成策略
            ②param:传递参数,当class=assigned时不需要配置
            ③常用的主键生成策略:assigned、increment、identity、sequence、native
            -->
            <generator class="assigned"/>
        </id>
        <!--
        property元素:定义持久化类中的属性和数据库表中的字段的对应关系
        -->
        <property name="deptName" type="java.lang.String" column="`DNAME`"/>

        <property name="loc" type="java.lang.String">
            <!--
            column元素:用于指定其父元素代表的持久化类属性所对应的数据库表中的字段
            ①name属性:表示字段名称
            ②length属性:表示字段长度
            ③not-null:设定是否不能为null
            -->
            <column name="`LOC`"></column>
        </property>
    </class>
</hibernate-mapping>

(6)在Hibernate核心配置文件中声明持久化类映射文件:

<session-factory>
    <!-- 其他配置 -->
    <!-- 映射配置文件 -->
    <mapping resource="mapping/Dept.hbm.xml"></mapping>
</session-factory>

使用Hibernate完成持久化操作

1、使用Hibernate操作数据库的步骤:

// 定义关键接口和类
Configuration conf = null;
SessionFactory sf = null;
Session session = null;
Transaction tx = null;

try {
    //1、读取并解析配置文件及映射文件
    conf = new Configuration().configure();

    //2、依据配置文件和映射文件中的信息创建SessionFactory对象
    sf = conf.buildSessionFactory();

    //3、打开SESSION
    session = sf.getCurrentSession();

    //4、开始一个事务
    tx = session.beginTransaction();

    //5、数据库操作
    Dept dept = new Dept();
    session.save(dept);

    //6、结束事务:提交
    tx.commit();
} catch (HibernateException e) {
    e.printStackTrace();
    //6、结束事务:回滚
    tx.rollback();
} finally {
    //7、关闭session
    session.close();
}

2、封装HibernateUtil工具类管理SessionFactory和Session:

public class HibernateUtil {
    private static Configuration configuration;
    private final static SessionFactory sessionFactory;

    static {
        try {
            configuration = new Configuration().configure();
            sessionFactory = configuration.buildSessionFactory();
        } catch (HibernateException ex) {
            throw new ExceptionInInitializerError(ex);
        }
    }

    private HibernateUtil() {}

    public static Session currentSession() {
        return sessionFactory.getCurrentSession();
    }
}

3、使用Hibernate实现按主键查询:

(1)get()方法加载:若数据不存在,返回null

//get方法:Object get(Class clazz, Serializable id)

public Dept get(Serializable id) {
    // 通过Session的get( )方法根据OID加载指定对象
    return (Dept) HibernateUtil.currentSession().get(Dept.class, id);
}

(2)load()方法加载:若数据不存在,使用时抛出ObjectNotFoundException异常。

//load方法:Object load(Class clazz, Serializable id)
public Dept load(Serializable id) {
    // 通过Session的load( )方法根据OID加载指定对象
    return (Dept) HibernateUtil.currentSession().load(Dept.class, id);
}

4、使用Hiberate实现增删改操作:

public void save(Dept dept) {
    currentSession().save(dept); // 保存指定的Dept对象
}

// 修改和删除操作时需要先加载数据
public void update(Dept dept) {
    currentSession().update(dept); // 更新指定的Dept对象
}

public void delete(Dept dept) {
    currentSession().delete(dept); // 删除指定的Dept对象
}

Hibernate中Java对象的三种状态

1、瞬时状态(Transient):通过new 创建对象之后,并没有立刻持久化,就是没有存储到数据库,还存储在内存中, 这就是瞬时状态,Session对瞬时状态是一无所知的,不受Session管理,如果对象没有被引用,将会被垃圾回收机制处理。

2、持久状态(Persistent):当对象与Session关联,被Session管理时,它就处于持久状态,处于持久状态的对象拥有数据库标识(主键值)例如刚从数据库中查出的对象。

3、游离状态(Detached):处于持久状态的对象,脱离预期关联的Session管理后,对象就处于游离状态,Hibernate无法感知该对象的任何操作。

4、三种状态之间的转换:

(1)瞬时状态转为持久状态:执行Session的save()、saveOrUpdate()方法对象从瞬间状态转换为持久状态,执行Session的get()、load()方法获取对象,该对象的状态就是持久状态。

(2)持久状态转为瞬时状态:执行Session的delete()方法后,对象由原来的持久状态变为瞬间状态,此时该对象灭有与任何数据库数据关联。

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

(4)游离状态转为持久状态:重新获取Session对象,执行Session对象的update()、saveOrUpdate() 方法,对象由游离状态转为瞬间状态 ,再次与Session关联。

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


脏检查及刷新缓存机制

1、刷新缓存:Session具有一个缓存,可以管理和追踪所有持久化对象,对象和数据库中的相关记录对应,在某些时间点,Session会根据缓存中对象的变化来执行相关SQL语句,将对象包含的变化数据更新到数据库中,这一过程成为刷新缓存。

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

2、脏检查:当刷新缓存时,Hibernate会对Session中的持久状态的对象进行检测,判断对象的数据是否发生了改变,这种判断称为脏检查。

3、刷新缓存机制:将数据库同步为与Session缓存一致。刷新缓存时会执行脏检查。

(1)调用Session的flush()方法时Session会刷新缓存。

(2)调用Transaction的commit()方法时Session会刷新缓存。


更新数据的方法

1、update()方法:用于将游离状态的对象恢复为持久状态,同时进行数据库更新操作。当参数对象的OID为null时会报异常。

2、saveOrUpdate()方法:同时包含了save()与update()方法的功能。

3、merge()方法:

(1)如果merge的对象在数据库中不存在,merge将会进行save操作,作用等同于saveOrUpdate();而update因为找不到对象而报错。

(2)如果merge的对象能在数据库中操作,merge操作和update操作效果一样。

(3)新new一个对象,如果该对象设置了ID,则这个对象就当作游离态处理。

(4)merge可以持久化游离态的对象A,持久化后的对象A仍然处于游离态,持久化的对象A不和session关联。

(5)merge返回持久化对象的副本,该副本处于持久化态。

如无特殊说明,本博所有文章均为博主原创。

如若转载,请注明出处:一木林多 - https://www.l5v.cn/archives/261/

评论