Hibernate框架之入门day01

自学了Hibernate之后印象不深,自我总结好好琢磨琢磨。

1.Hibernate框架简述

1.1 ORM框架

Hibernate是一个数据持久化层的ORM框架.
Object:对象,java对象,此处特指JavaBean
Relational:关系,二维表,数据库中的表。
映射|映射元数据:对象中属性,与表的字段,存在对应关系。这里写图片描述

1.2Hibernate的体系结构

1.2.1Hibernate的核心组件
在基于MVC设计模式的JAVA WEB应用中,Hibernate可以作为模型层/数据访问层。它通过配置文件(hibernate.properties或hibernate.cfg.xml)和映射文件(*.hbm.xml)把JAVA对象或PO(Persistent Object,持久化对象)映射到数据库中的数据库,然后通过操作PO,对数据表中的数据进行增,删,改,查等操作。

a ) PO:persistent object ,用于与数据库交互数据。–dao层 (JavaBean + hbm )
b ) BO:Business object 业务数据对象。–service层
c ) VO:Value Object 值对象。–web层 这里写图片描述
1.2.2hibernate 核心配置文件种类
a) hibernate.cfg.xml= 通常使用xml配置文件,可以配置内容更丰富。(经常用
b) hibernate.properties 用于配置key/value 形式的内容,key不能重复的。配置有很多的局限性。(一般不用
c)xxx.hbm.xml映射文件由节点定义映射内容并指定所对应的JavaBean的位置(也可以不在该节点中用package属性指定对应的JavaBean位置,而在该节点下的class节点中的name属性中指定), 是Hibernate与数据库进行持久化的桥梁

除配置文件,映射文件和持久化类外,Hibernate的核心组件包括以下几部分:
a)Configuration类:用来读取Hibernate配置文件,并生成SessionFactory对象。
b)SessionFactory接口:产生Session实例工厂。
c)Session接口:用来操作PO。它有get(),load(),save(),update()和delete()等方法用来对PO进行加载,保存,更新及删除等操作。它是Hibernate的核心接口。
d)Query接口:用来对PO进行查询操。它可以从Session的createQuery()方法生成。
e)Transaction接口:用来管理Hibernate事务,它主要方法有commit()和rollback(),可以从Session的beginTrancation()方法生成。

1.2.3Persistent Object
持久化对象可以是普通的Javabeans,惟一特殊的是它们与(仅一个)Session相关联。JavaBeans在Hibernate中存在三种状态:

  • 临时状态(transient):当一个JavaBean对象在内存中孤立存在,不与数据库中的数据有任何关联关系时,那么这个JavaBeans对象就称为临时对象(Transient
    Object)。
  • 持久化状态(persistent):当一个JavaBean对象与一个Session相关联时,就变成持久化对象(Persistent
    Object)
  • 脱管状态(或者叫游离状态(detached):在这个Session被关闭的同时,这个对象也会脱离持久化状态,就变成脱管状态(Detached Object),可以被应用程序的任何层自由使用,例如可以做与表示层打交道的数据舆对象(Data Transfer Object)。

1.2.4Hibernate的运行过程
Hibernate的运行过程如下:

  • 应用程序先调用Configration类,该类读取Hibernate的配置文件及映射文件中的信息,并用这些信息生成一个SessionFactory对象。

  • 然后从SessionFactory对象生成一个Session对象,并用Session对象生成Transaction对象;可通过Session对象的get(),load(),save(),update(),delete()和saveOrUpdate()等方法对PO进行加载,保存,更新,删除等操作;在查询的情况下,可通过Session对象生成一个Query对象,然后利用Query对象执行查询操作;如果没有异常,Transaction对象将提交这些操作结果到数据库中

这里写图片描述

2.入门案例

2.1编写流程
 1. 创建数据库和表
 2. 导入jar包
 3. 编写核心配置文件(hibernate.cfg.xml)–> 配置获得链接等参数
 4. 编写映射文件 hibernate mapping(*.hbm.xml)
 5 使用api测试
2.2创建数据库和表

create database hibernate;
use hibernate;
create table t_user(
  id int auto_increment primary key,
  username varchar(50),
  password varchar(30)
);

2.3导入jar包
这里写图片描述 这里写图片描述

2.4. 编写JavaBean+映射文件
 a)文件位置:javabean同包
 b)文件名称:javabean同名
 c)扩展名:*.hbm.xm l 这里写图片描述

User

public class User {
    private int id;
    private String name;
    private String password;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

}

User.hbm.xml

<?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="com.User" table="t_user">
        <id name="id" column="id">
            <generator class="native"></generator>
        </id>
        <property name="name" column="name"></property>
        <property name="password" column="password"></property>
    </class>
</hibernate-mapping>    

2.5 编写核心配置文件
 a)位置:类路径(classpath、src)–>WEB-INF/classes
 b)名称:hibernate.cfg.xml
 c)内容:添加约束

<?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>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">tracydzf</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate</property>

        <property name="show_sql">true</property>
        <property name="format_sql">true</property>

        <property name="hbm2ddl.auto">update</property>
        <property name="hibernate.connection.autocommit">true</property>

        <property name="hibernate.current_session_context_class">thread</property>



        <mapping resource="com/User.hbm.xml"/>

    </session-factory>
</hibernate-configuration>

2.6测试

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;
import org.junit.Test;

public class test1 {
    @Test
    public void fun() {
        // 1读取配置文件
        Configuration conf = new Configuration().configure();
        // 2根据配置创建factory
        SessionFactory sf = conf.buildSessionFactory();
        // 3获得session
        Session session = sf.openSession();
        // 4操作数据库
        User u = new User();
        u.setName("tom");
        u.setPassword("1234");
        session.save(u);
        // 5关闭资源
        session.close();

        sf.close();

    }

}

3.API详解

3.1 Configuration 配置对象

  • hibernate.cfg.xml 通常使用xml配置文件,可以配置内容更丰富。
  • hibernate.properties 用于配置key/value 形式的内容,key不能重复的。配置有很多的局限性。一般不用。

3.1.1 加载核心配置文件

加载hibernate.properties时:Configuration configuration = new Configuration();

加载hibernate.cfg.xml时:Configuration configuration = new Configuration().configure();

3.1.2 加载映射文件(不过,一般映射文件都配置在核心配置文件中,该方法用少)

        // 手动加载指定的配置文件
        config.addResource("com/itheima/a_hello/User.hbm.xml");

        // 手动加载指定类,对应的映射文件 User--> User.hbm.xml
        config.addClass(User.class);

3.1.3常见异常
这里写图片描述

  • 开发中:将hbm.xml映射 配置 hibernate.cfg.xml
  • 学习中:可以使用 addClass 或 addResource

3.2 SessionFactory工厂

  • SessionFactory负责管理Session,管理连接池,管理Hibernate二级缓存。是一个重量级的, 线程安全的对象.
  • SessionFactory 相当于java web连接池,用于管理所有session
  • 获得方式:config.buildSessionFactory();
  • sessionFactory hibernate缓存配置信息 (数据库配置信息、映射文件,预定义HQL语句 等)
  • SessionFactory线程安全,可以是成员变量,多个线程同时访问时,不会出现线程并发访问问题。
//打开一个新的会话 session
factory.openSession();
//获得当前线程中绑定的会话session
factory.getCurrentSession();

hibernate支持,将创建的session绑定到本地线程中,底层使用ThreadLocal,在程序之间共享session。

  • 1.必须在hibernate.cfg.xml 配置
  • <!-- 2 与本地线程绑定 -->
    <property name="hibernate.current_session_context_class">thread</property>
  • 2.如果提交或回滚事务,底层将自动关闭session

3.3 Session 会话

 Session是Hibernate程序与数据库之间的桥梁。完成CRUD的操作。Session是一个单线程的对象,内部维护了Hibernate的一级缓存。

  • hibernate的一级缓存—>session级别的缓存
  • 一级缓存是session级别的缓存, 同session的声明周期一直. 一级缓存实际上是由session中的一组集合构成的.

  • 一级缓存的主要作用: 减少对数据库的访问次数

  • 执行原理: 在session中执行查询操作时,首先会从缓存中获取结果, 如果缓存中没有, 则去数据库中查询,
    并将查询结果往缓存中存放一份; 如果缓存中有, 则直接从缓存中获取.

  • 一级缓存快照区: 在存放在缓存中的数据会在session一级缓存的快照区存放一份, 当数据发生变更时, 缓存中的数据会被修改,而快照区的数据还是原来的数据, 在事务提交时, 会对比一级缓存和快照区, 如果数据不一致, 则会发送sql语句更改数据库中数据;如果数据一致, 则不对数据库进行更新操作. 因此, 对于持久态的对象, 即使没有显示的添加update语句, 如果数据发生变化,在提交事务时, 会自动更新数据库

      session保存一个对象: session.save(entity);

      session修改对象:session.update(entity);

      session删除对象session.delete(entity);

      session查询对象:session.get()和session.load();
      
       获得Query对象:createQuery("hql")
      
       获得Criteria对象 :createCriteria(Class)

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

相同点:

  • 都是通过id进行查询

不同点:

  • 加载机制不同. get方法采用的是立即加载,执行到代码的时候,立即发送SQL语句进行查询;
    而load方法采用的延迟加载(Lazy)机制, 执行该代码的  时候不会马上发送SQL语句,只有真正使用该对象的时候才会发送SQL语句查询

  • 查询结果不同. get方法查询得到的是对象本生, 而load方法查询返回的一个代理对象;

  • 查询没有找到时的处理应答不同, get方法返回的是null; 而load方法则会抛出异常ObjectNotFoundException;

3.4 Transaction 事务

  • 开启事务 beginTransaction()
  • 获得事务 getTransaction()
  • 提交事务:commit()
  • 回滚事务:rollback()
try{
   //开启
   //session操作
   //提交
} catch(e){
   //回滚
}
//扩展:不需要手动的管理事务,之后所有的事务管理都交予spring。

3.5 Query 对象

  • hibernate执行hql语句

  • hql语句:hibernate提供面向对象查询语句,使用对象(类)和属性进行查询。区分大小写。

  • 获得 session.createQuery("hql")

  • 方法:
    -list() 查询所有
    -uniqueResult() 获得一个结果。如果没有查询到返回null,如果查询多条抛异常。

    -setFirstResult(int) 分页,开始索引数startIndex
    -setMaxResults(int) 分页,每页显示个数 pageSize

4.Hibernate中HibernateUtil工具类

首先我们需要知道为什么咱们要创建Hibernate工具类?

一些固定而且经常使用的步骤我们期望做成一个工具类,以后再需要重复步骤时咱们仅需要引用此工具类就可以,从而避免了一直创建重复代码。比如加载数据库的驱动等,这里Hibernate中我们每个主程序都需要加载hibernate.cfg.xml文件、创建SessionFactory对象、创建Session对象、关闭session。这些都是固定化的步骤,因此我们将它们写在工具类HibernateUtil中,以后咱们直接引用此文件创建各对象即可,大大减少了代码量,提高了代码复用性。

最佳版本:

/**
 * 该工具类提供了一个属性:SessionFactory sessionFactory 
 * 并创建了sessionFactory 将它设置成static 这样其他程序就可以直接通过此工具类引用
 * 提供了二个方法:
 * 1:通过线程创建Session-->currentSession()
 * 2:关闭Session-->closeSession()
 * 需要在主类中手动关闭sessionFactory
 */
public class HibernateUtil
{
    public static final SessionFactory sessionFactory;
    //创建sessionFactory
    static
    {
        try
        {
            // 采用默认的hibernate.cfg.xml来启动一个Configuration的实例
            Configuration cfg = new Configuration()
                .configure();
            // 以Configuration实例来创建SessionFactory实例
            ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
                .applySettings(cfg.getProperties()).build();
            sessionFactory = cfg.buildSessionFactory(serviceRegistry);
        }
        catch (Throwable ex)
        {
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    // ThreadLocal可以隔离多个线程的数据共享,因此不再需要对线程同步
    public static final ThreadLocal<Session> session
        = new ThreadLocal<Session>();
    //创建Session
    public static Session currentSession()
        throws HibernateException
    {
        //通过线程对象.get()方法安全创建Session
        Session s = session.get();
        // 如果该线程还没有Session,则创建一个新的Session
        if (s == null)
        {
            s = sessionFactory.openSession();
            // 将获得的Session变量存储在ThreadLocal变量session里
            session.set(s);
        }
        return s;
    }
    //关闭Session
    public static void closeSession()
        throws HibernateException
    {
        Session s = session.get();
        if (s != null)
            s.close();
        session.set(null);
    }
}

我的版本

public class H3Utils {

    // 会话工厂,整个程序只有一份。
    private static SessionFactory factory;

    static{
        //1 加载配置
        Configuration config = new Configuration().configure();

        //2 获得工厂
        factory = config.buildSessionFactory();
//3 关闭虚拟机时,释放SessionFactory
            Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {

            @Override
            public void run() {
                System.out.println("虚拟机关闭!释放资源");
                sf.close();
            }
        }));
    }


    /**
     * 获得一个新的session
     * @return
     */
    public static Session openSession(){
        return factory.openSession();
    }

    /**
     * 获得当前线程中绑定session
     * * 注意:必须配置
     * @return
     */
    public static Session getCurrentSession(){
        return factory.getCurrentSession();
    }


}

5.核心配置文件详解

Hibernate核心配置文件hibernate.cfg.xml主要由以下四部分组成:
- (1)数据库连接信息,包括驱动程序类名、连接URL、用户名和密码。
- (2)Hibernate相关特性,包括dialect(方言)、show_sql(输出SQL语句到控制台)、format_sql(格式化SQL语句)
- (3)连接池相关信息。
- (4)实体类映射文件,实体类与数据库表之间的逻辑映射

<!-- SessionFactory,相当于之前学习连接池配置 -->
    <session-factory>
        <!-- 1 基本4项 -->
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql:///hibernate</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">tracydzf</property>

        <!-- 2 与本地线程绑定 -->
        <property name="hibernate.current_session_context_class">thread</property>

        <!-- 3 方言:为不同的数据库,不同的版本,生成sql语句(DQL查询语句)提供依据 
            * mysql 字符串 varchar
            * orcale 字符串 varchar2
        -->
        <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>

        <!-- 4 sql语句 -->
        <!-- 显示sql语句 -->
        <property name="hibernate.show_sql">true</property>
        <property name="hibernate.format_sql">true</property>

        <!-- 5 自动创建表(了解) ,学习中使用,开发不使用的。
            * 开发中DBA 先创建表,之后根据表生产 PO类
            * 取值:
            update:【】
                如果表不存在,将创建表。
                如果表已经存在,通过hbm映射文件更新表(添加)。(映射文件必须是数据库对应)
                    表中的列可以多,不负责删除。
            create :如果表存在,先删除,再创建。程序结束时,之前创建的表不删除。【】
            create-drop:与create几乎一样。如果factory.close()执行,将在JVM关闭同时,将创建的表删除了。(测试)
            validate:校验 hbm映射文件 和 表的列是否对应,如果对应正常执行,如果不对应抛出异常。(测试)
        -->
        <property name="hibernate.hbm2ddl.auto">update</property>

        <!-- 6 java web 6.0 存放一个问题
            * BeanFactory 空指针异常
                异常提示:org.hibernate.HibernateException: Unable to get the default Bean Validation factory
            * 解决方案:取消bean校验
        -->
        <property name="javax.persistence.validation.mode">none</property>


        <!-- 7连接池的配置 -->
        <property name="hibernate.connection.provider_class">
        org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider
        </property>

        <!-- 8C3P0随机准备好的最少的JDBC连接数量 -->
        <property name="hibernate.c3p0.min_size">5</property>

        <!-- 9连接池的最大JDBC连接数量 -->
        <property name="hibernate.c3p0.max_size">20</property>

        <!--10 配置超时周期,在他之后,休闲连接将从连接池中移除 -->
        <property name="hibernate.c3p0.timeout">300</property>

        <!-- 11注册ORM添加映射文件 
            <mapping >添加映射文件
                resource 设置 xml配置文件 (addResource(xml))
                class 配置类 (addClass(User.class)) 配置的是全限定类名
        -->
        <mapping  resource="com/itheima/a_hello/User.hbm.xml"/>
    </session-factory>

参考:
https://www.cnblogs.com/rodge-run/archive/2017/02/19/6415594.html
https://www.jianshu.com/p/50964e92c5fb
https://blog.csdn.net/vipmao/article/details/51340525
http://www.cnblogs.com/zhangzongle/p/5738786.html

猜你喜欢

转载自blog.csdn.net/qq_41955282/article/details/81263581