【Hibernate】从0开始学Hibernate--002。Hibernate*Session详解

Hibernate从0开始,第一部分初涉Hibernate搭建第一个简单的Hibernate框架

https://blog.csdn.net/hekaikai666/article/details/81672688

回顾与总结:

简述上一章的主要内容:

(一)Hibernate框架的概念:数据持久层的ORM框架,主要作用是用于操作数据库,简化封装了JDBC的操作

(二)Hibernate框架的优点:开发效率高、可移植性好、完全面向对象、多表级联操作、精细数据缓存、延迟加载。

(三)Hibernate框架的缺点:特定SQL语句优化、大规模批量数据处理

(四)ORM对象映射关系:Hibernate属于第四级(一共四级)

(五)Hibernate框架使用步骤:

        1、创建数据库;

        2、创建项目并导入两大核心包;

        3、导入Hibernate主配置文件;

        4、根据数据库中的表创建相应的实体类;

        5、编写映射文件;

        6、加载映射文件;

        7、执行相关数据库操作;

接下来,我们就应该学习如何操作数据库。首先要了解几个概念:SessionFactory和Session和Configuration,这三个都是Hibernate操作做数据库常用的接口,那么他们究竟是用来干什么的呢?

Session接口:

    Session接口对于Hibernate以至于开发人员来说是一个非常重要的接口。Hibernate中,实例化的Session是的接口类,创建和销毁它都不会占用很多资源。这在实际项目 中确实很重要,因为在客户程序中,可能会不断地创建以及销毁Session对象,如果Session的开销太大,会给系统带来不良影响。但值得注意的是 Session对象是非线程安全的,因此在你的设计中,最好是一个线程只创建一个Session对象。   
    在Hibernate的设计者的脑中,他们将session看作介于数据连接与事务管理一种中间接口。我们可以将session想象成一个持久化对象的缓冲区,Hibernate能检测到这些持久对象的改变,并及时刷新数据库。我们有时也称Session是一个持久层管理器,因为它包含这一些持久层相关的操作,诸如存储持久对象至数据库,以及从数据库从获得它们。区别于JSP九大内置对象中的session,Hibernate的session不同于JSP应用中的HttpSession。当我们使用session这个术语时,我们指的是Hibernate中的session,我将HttpSesion对象称为用户session。   

SessionFactory接口:

    这里用到了一个设计模式――工厂模式,用户程序从工厂类SessionFactory中取得Session的实例。(之后会详细的讲Java中的6中设计原则和23种设计模式)
    SessionFactory并不是轻量级的!实际上它的设计者的意图是让它能在整个应用中共享。典型地来说,一个项目通常只需要一 个SessionFactory就够了,但是当你的项目要操作多个数据库时,那你必须为每个数据库指定一个SessionFactory。 所以SessionFactory中就是用来操作各种session的,具体详解到下贴中关于缓存机制。  SessionFactory在Hibernate中实际起到了一个缓冲区的作用,它缓冲了Hibernate自动生成的SQL语句和一些其它的映射数据,还缓冲了一些将来有可能重复利用的数据。   

Configuration接口 :

Configuration接口的作用是对Hibernate进行配置,以及对它进行启动。在Hibernate的启动过程中,Configuration类的实例首先定位映射文档的位置,读取这些配置,然后创建一个SessionFactory对象。相当于在Java类中继承关系,而Configuration就是用来与SessionFactory来继承操作的。

一、Session操作数据库。

        首先我们了解几个代名词: 

       DML--指的是数据操纵语言,eg:insert into ,update ,delete
       DQL--数据库查询语言,  eg:select
       DDL--数据库模式定义语言   eg:create   alter    drop
       DCL==数据库控制语言    eg:grant     revoke
       TCL--事务控制语言    eg:commit
       DDL,DML,DCL,DQL,TCL共同组成数据库的完整语言。

        (一)那么我们的DML数据操作语言就是基础操作数据库的语言,主要实现的功能是增、删、改的语句,他们有一个共同的特点:数据操作需要开启和关闭事务。当然也需要事务控制语句来提交。

       首先提出一个获取工厂类的方法:因为使用session就需要创建项目有且仅有唯一的一个SessionFactory工厂。

public static SessionFactory getSessionFactory() {
	// 实例化主配置加载Configuration类对象
	Configuration cf = new Configuration();
	// 加载项目主配置文件
	cf.configure("hibernate.cfg.xml");
	// 获取sessionFactory工厂对象
	SessionFactory factory = cf.buildSessionFactory();
	// 返回SessionFactory对象
	return factory;
}

       数据库增加操作:session.save(Object);需要注意的是添加事务要进行提交,任何执行都需要Session对象关闭。

/**
 * 通过session对象添加数据
 * 
 * @param factory
 *            sessionFactory工厂对象
 */
 private static void insert(SessionFactory factory) {
 	// 通过工厂获取Session 对象
	Session session = factory.openSession();
	// 使用对象开启事务
	Transaction begin = session.beginTransaction();
	// 创建一个实体对象
	Dept dept = new Dept(2, "凯宝宝自造有限公司", "西安");
	// 使用Session往数据库中插入一条数据
	session.save(dept);
	// 提交事务
	begin.commit();
	// 关闭session
	session.close();
 }

         数据库删除操作:session.delete(Object);需要注意的是删除事务要进行提交,任何执行都需要Session对象关闭,删除需要操作2条SQL语句,第一句是查询此条,然后执行第二条删除。

/**
 * 通过session对象删除数据
 * 
 * @param factory
 *            sessionFactory工厂对象
 */
 private static void delete(SessionFactory factory) {
	// 获取session对象
	Session session = factory.openSession();
	// 开启事务
	Transaction begin = session.beginTransaction();
	// 根据id查找要删除的对象
	Dept dept = (Dept) session.get(Dept.class, 3);
	// 执行删除
	session.delete(dept);
	// 提交事务
	begin.commit();
	// 关闭session
	session.close();
}

        数据库修改操作:session.(); 需要注意的是,数据库先进行查询,然后进行数据删除,在把新的数据加入,所以需要执行3条SQL语句。

/**
 * 通过session对象修改数据
 * 
 * @param factory
 *            sessionFactory工厂对象
 */
 private static void update(SessionFactory factory) {
	// 通过工厂获取Session 对象
	Session session = factory.openSession();
	// 使用对象开启事务
	Transaction begin = session.beginTransaction();
	// 创建一个对象
	Dept dept = new Dept(3, "凯宝宝自造有限公司", "美国");
	// 修改数据:先查询表中是否有这条数据,没有就插入,有就看数据是否一致,一致不做任何操作,如果不一致就执行操作修改
	session.update(dept);
	// 提交事务
	begin.commit();
	// 关闭session
	session.close();
 }

        数据库保存并修改:session.saveOrUpdate(Object);先查询表中是否有这条数据,没有就插入,有就看数据是否一致,一致不做任何操作,如果不一致就执行操作修改

/**
 * 通过session对象修改数据
 * 
 * @param factory
 *            sessionFactory工厂对象
 */
 private static void update(SessionFactory factory) {
	// 通过工厂获取Session 对象
	Session session = factory.openSession();
	// 使用对象开启事务
	Transaction begin = session.beginTransaction();
	// 创建一个对象
	Dept dept = new Dept(3, "凯宝宝自造有限公司", "美国");
	// 修改数据:先查询表中是否有这条数据,没有就插入,有就看数据是否一致,一致不做任何操作,如果不一致就执行操作修改
	session.saveOrUpdate(dept);
	// 提交事务
	begin.commit();
	// 关闭session
	session.close();
 }

        (二)数据库简单的查询操作:根据ID查询一条属性(对象中),数据库中则需要调用两个方法get() 或 load();

                get():只要调用此方法就会立即向数据库发送一条查询语句;并可以返回查询结果对象;属于非延迟加载机制,当无法查询到此id对应的对象数据时,会报出一个NullPointerException空指针异常。

                load():只要访问对象的非查询属性(ID)才会对数据库进行发送操作,属于延迟加载机制。当无法查询到此id对应的数据时,会报出一个ObjectNotFoundException对象未找到异常。

/**
     * 根据ID查询一个对象. 
     * 
     * @param factory
     *            sessionFactory工厂对象
     */
    private static void select1(SessionFactory factory) {
	// 获取session对象
	Session session = factory.openSession();
	// 直接id查询一个对象
	Dept dept1 = (Dept) session.get(Dept.class, 10);
        Dept dept = (Dept) session.load(Dept.class, 10);
        System.out.println("load:"+dept.getDname());
	// session中get和load的区别
	// get只要调用get方法,就会把所有的字段加载到内存中,如果访问不在id范围内的属性则会NullPointerException(空指针异常)
	// load只要使用了返回的对象,才会运行加载的方法(访问非ID属性)如果访问不在id范围内的属性则会ObjectNotFoundException(对象未找到异常)
}

对于Session查询获取中使用get()和load()方法,当然会呈现不同的状态,而在session中会有三中不同的对象存储方式:临时状态、持久状态、游离状态。

二、Hibernate中对象存储的三种状态。

        a.临时状态:临时状态对象(瞬时态) 内存中有对象,数据库中没有与之相对应的数据

        b.持久状态:内存中有对象,数据库中有与之对应的数据,当修改对象的属性时,数据库中的数据也会跟着自动更改

        c.游离状态:游离状态对象 内存中有对象,数据库中有与之对应的数据,但是对象处理离线状态,修改对象的属性,数据库中数据不会跟着被修改

/**

* 临时状态对象(瞬时态) 内存中有对象,数据库中没有与之相对应的数据

* 什么样的对象是临时状态?新创建的对象;持久状态的对象调用了delete()方法

*/

/**

* 持久状态对象 内存中有对象,数据库中有与之对应的数据,当修改对象的属性时,数据库中的数据也会跟着自动更改(缓存在session缓存中...)

* 什么样的对象是持久状态的对象?新创建的对象调用了save()或者saveOrUpdate();通过get()或者load()方法从数据库中加载出来的对象;游离态对象调用了update或者saveOrUpdate将变回持久态

*/

 

/**

* 游离状态对象 内存中有对象,数据库中有与之对应的数据,但是对象处理离线状态,修改对象的属性,数据库中数据不会跟着被修改

* 什么样的对象是游离态呢?session关闭时(.close());从session缓存中踢出了某个持久态对象(.evick());清空session缓存(.clear())

*/

临时状态和游离状态随时都有可能被垃圾回收...

上面这些文字相信你也云里雾里,那么下面我来用一张图来详细解释一下这三种状态的转换关系。

 

 当创建new()一个新的对象的时候,所创建的对象就处于临时状态,此时的对象存储与内存当中当调用了save()(非延迟加载)或者saveOrUpdate()(延迟加载,需要使用非查询属性之后方可执行)方法之后。与数据库产生交互,对象也就变成持久状态,在内存中和在数据库中均有对象属性存在,此时执行修改的方法,内存中和数据库中的数据均做修改。当对象调用delete()方法后,删除掉数据库中的数据,对象中的属性也就变成了临时态,但是临时态是不会被清理的。当session对象关闭,清除或者踢出的方法时,持久态的属性也就变成了游离态(对象依旧在内存中,但是与数据库的连接已经断开,所以执行增删改的方法只会影响对象不会影响数据库中的内容)当重新建立连接(创建新的session对象后)调用save()或者saveOrUpdate()方法,又将变成持久态。当程序关闭的时候,也就是游离态的对象无法再进行操作的时候,就只能等待PC的垃圾处理机制,随机的清理掉对象的属性,但不会影响到数据库的操作。

三、脏数据与刷新缓存

        什么是脏数据?为什么存在脏数据?

        脏数据:当session缓存中持久态对象的数据发生了变化,而数据库中的数据未发生改变,这个对象是脏对象(脏数据)。在数据库技术中,脏数据在临时更新(脏读)中产生。事务A更新了某个数据项X,但是由于某种原因,事务A出现了问题,于是要把A回滚。但是在回滚之前,另一个事务B读取了数据项X的值(A更新后),A回滚了事务,数据项恢复了原值。事务B读取的就是数据项X的就是一个“临时”的值,就是脏数据。

        为了针对出现脏数据的问题,session中有一种检查机制,使数据库中的数据与对象中的数据保持一致,就叫做脏检查;脏检查就是检查数据库中数据是否和session缓存中持久态对象数据一致,如果不一致,则在刷新缓存时,将数据库中数据刷新为与session缓存中一致。一句话:刷新数据库中的数据和session对象中的数据保持一致

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值