文档章节

Hibernate<二> - Session

Mr_ET
 Mr_ET
发布于 2017/08/17 10:28
字数 2656
阅读 11
收藏 2
点赞 0
评论 0

1、Session概述

    Session接口是Hibernate向应用程序提供的操纵数据库的最主要的接口,它提供了基本的保存更新删除加载Java对象的方法。

    每一个Session对象都在内存中维护了一个缓存,位于缓存中的对象称为持久化对象,它和数据库表中的相关记录保持着一种对应关系。通过Session缓存,Hibernate最大限度的减少了应用程序访问数据库的次数,实现了对内存空间更加有效的利用。

    Hibernate把持久化类的对象分为4种状态:持久化状态临时状态游离状态删除状态。Session的特定方法能使对象从一个状态转换到另一个状态。

2、Session缓存

    在应用系统开发过程中,使用缓存往往是提升程序性能的主要手段。在Hibernate中,Session对象维护的是一个线程级的一级缓存,SessionFactory维护了一个进程级别的二级缓存。二级缓存会在后面的博客中详细介绍,现在先关注Session维护的一级缓存。

    2.1  使用Session缓存的好处

        ①减少访问数据库的次数

        两次调用session.get(Student.class,1);方法,仅发送1条SQL语句。原因是第一次使用get()方法加载的Student被缓存到了内存中,第二次调用get()方法直接使用了内存中缓存的Student对象,从而减少了访问数据库的次数

    Tips:应用程序中访问数据库的次数往往是最主要的性能瓶颈。

        ②将内存中数据的变化自动同步到数据库中

    使用session.get(Student.class,1);方法将一个Student对象加载到内存中后,Student对象就处于Session对象的管理中。此时调用student.setStuName(“a”);方法将触发Hibernate对数据库表中对应数据记录的修改,即发送一条UPDATE语句,更新Student对象在数据库表中对应的记录。

    Hibernate最大的特点就是将对数据库记录的操作,转换为对Java对象的操作简化开发

2.2 Session缓存操作概述

    ①flush:推送。将缓存中数据的改变落实到数据库中

    ②refresh:刷新。将数据库中数据的改变提取到缓存中

    ③clear:清空。清空Session缓存

2.3    flush操作
    ①Session对象默认在什么情况下执行flush操作?
    ②默认情况下Session执行flush操作的时机:
        [1]显式调用Session的flush()方法
        [2]调用Transaction对象的commit()方法时,先flush缓存,在提交事务
        [3]执行HQL、QBC查询之前,先flush缓存,保证HQL或QBC查询到的数据是最新的。
    ③相关问题
        [1]修改持久化对象的属性值,并不会立即发送SQL语句,而是提交事务之前,执行flush操作的时候才会发送相应的UPDATE语句。
        [2]发送UPDATE语句时,数据的修改并不会立即生效,只有提交了事务之后,数据的修改才会永久的保存下来。

2.4    refresh操作与事务隔离级别
①提出问题
在使用MySQL客户端修改数据后,refresh()方法读取到的还是旧的未修改的数据,为什么?
②分析
MySQL默认的数据库事务隔离级别是“可重复读”,要保证当前事务执行期间的不同时间点读取到的数据是一样的。
③结论
refresh()方法读取到的数据是不是真正的最新数据,需要参照当前的事务隔离级别。
3    事务隔离级别回顾
3.1    数据库事务并发问题
假设现在有两个事务:Transaction01和Transaction02并发执行。
①脏读
    [1]Transaction01将某条记录的AGE值从20修改为30。
    [2]Transaction02读取了Transaction01更新后的值:30。
    [3]Transaction01回滚,AGE值恢复到了20。
    [4]Transaction02读取到的30就是一个无效的值。
②不可重复读
    [1]Transaction01读取了AGE值为20。
    [2]Transaction02将AGE值修改为30。
    [3]Transaction01再次读取AGE值为30,和第一次读取不一致。
③幻读
    [1]Transaction01读取了STUDENT表中的一部分数据。
    [2]Transaction02向STUDENT表中插入了新的行。
    [3]Transaction01读取了STUDENT表时,多出了一些行。
3.2    隔离级别
    数据库系统必须具有隔离并发运行各个事务的能力,使它们不会相互影响,避免各种并发问题。一个事务与其他事务隔离的程度称为隔离级别。SQL标准中规定了多种事务隔离级别,不同隔离级别对应不同的干扰程度,隔离级别越高,数据一致性就越好,但并发性越弱。
    ①读未提交:READ UNCOMMITTED
        允许Transaction01读取Transaction02未提交的修改。
    ②读已提交:READ COMMITTED
        要求Transaction01只能读取Transaction02已提交的修改。
    ③可重复读:REPEATABLE READ
        确保Transaction01可以多次从一个字段中读取到相同的值,即Transaction01执行期间禁止其它事务对这个字段进行更新。
    ④串行化:SERIALIZABLE
        确保Transaction01可以多次从一个表中读取到相同的行,在Transaction01执行期间,禁止其它事务对这个表进行添加、更新、删除操作。可以避免任何并发问题,但性能十分低下。
    ⑤各个隔离级别解决并发问题的能力见下表

    ⑥各种数据库产品对事务隔离级别的支持程度

⑦在MySQL中设置隔离级别

    [1]每启动一个MySQL程序,就会获得一个单独的数据库连接。每个数据库连接都有一个全局变量@@tx_isolation,表示当前的事务隔离级别。

    [2]查看当前的隔离级别:

SELECT @@tx_isolation;

    [3]设置当前MySQL连接的隔离级别:

SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

    [4]设置数据库系统的全局的隔离级别:

SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;

    ⑧在Hibernate中设置隔离级别

    [1]JDBC数据库连接使用数据库系统默认的隔离级别。

    [2]在Hibernate的配置文件中可以显式的设置隔离级别。每一个隔离级别都对应一个整数:

    [3]设置方式

<!-- 设置当前数据库事务隔离级别为读已提交 -->
<property name="hibernate.connection.isolation">2</property>

4    持久化对象的状态
    4.1    四种状态
    ①临时状态
        [1]OID:没有OID。例如:new Student(null, "Kate2015", 18, new Date());
        [2]是否在Session缓存中:不在
        [3]是否在数据库中有对应的记录:没有
    ②持久化状态
        [1]OID:有OID。例如:Student student = (Student) session.get(Student.class, 1);
        [2]是否在Session缓存中:在
        [3]是否在数据库中有对应的记录:有
    ③游离状态
        [1]OID:有OID。例如:new Student(1, "Kate2015", 18, new Date());
        [2]是否在Session缓存中:不在
        [3]是否在数据库中有对应的记录:有
    ④删除状态
        [1]OID:有OID。通常是经过删除操作得到的。
        [2]是否在Session缓存中:不在
        [3]是否在数据库中有对应的记录:没有

4.2    四种状态之间的转换

5    Session核心方法
    5.1    save()
        ①将一个临时对象转换为持久化对象
        ②对于OID:忽略临时对象中的“OID”值,save()方法会将数据库产生的新的OID的值赋值给持久化对象
        ③持久化状态的对象的OID的值是不允许修改的
    5.2    persist()
        ①作用和save()相同
        ②不允许保存带有OID的对象,会抛异常:org.hibernate.PersistentObjectException
    5.3    get()
        ①根据OID的值,从数据库中立即加载一个对象到内存中。
        ②如果调用get()方法时,Session缓存中已经有了一个OID相同的对象,则get()方法会将缓存中的对象返回,不发送SQL语句。
    5.4    load()
        ①采用延迟检索策略,在调用load()方法时仅返回一个代理对象,不发送SQL语句。在真正用到非OID属性值时,才发送SQL语句进行查询。
        ②懒加载初始化异常
        [1]全类名:org.hibernate.LazyInitializationException
        [2]产生原因:对一个延迟加载的代理对象进行初始化时,Session缓存中没有对应OID的对象,无法完成初始化。
5.5    update()
    ①根据游离对象或持久化对象对数据库表进行更新
    ②update()方法更新一个游离对象时,默认情况下无法获知当前游离对象中的数据和数据库表中的数据是否有差异。所以,无论是否有差异都会发送SQL语句。为了避免盲目的发update语句,可以在hbm配置文件的class元素中设置select-before-update属性的值为true。通常不设置这个属性。
    ③使用update()方法更新一个OID不存在的对象会抛出异常:org.hibernate.StaleObjectStateException
    ④使用update()方法更新一个游离对象,但此时Session缓存中已经存在了OID相同的持久化对象,会抛出异常:org.hibernate.NonUniqueObjectException
5.6    saveOrUpdate()
    ①兼具保存和更新两种功能。传入临时对象执行保存,传入游离对象执行更新。
    ②判断执行INSERT语句还是UPDATE语句的依据
    [1]根据OID的值,如果为null则执行保存,否则执行更新
    [2]如果OID的值等于hbm文件中,id元素设置的unsaved-value属性则执行保存操作。
5.7    delete()
    ①执行删除操作
    ②删除对象后将OID的值置空:在Hibernate配置文件中加入如下配置

<property name="hibernate.use_identifier_rollback" >true </property>

5.8    doWork()
    ①用于在Hibernate环境下执行原生的JDBC代码
    ②示例代码

@Test
public void testWork() {
	session.doWork(new Work() {
		
		@Override
		public void execute(Connection connection) throws SQLException {
			
			//使用传入的Connection对象实现原生的JDBC操作...
			
		}
	});
}

 GitHub地址:https://github.com/leebingbin/  

© 著作权归作者所有

共有 人打赏支持
Mr_ET
粉丝 30
博文 89
码字总数 122971
作品 0
朝阳
高级程序员
简单理解Hibernate三种状态的概念及互相转化

本文描述了Hibernate三种状态的概念及互相转化。Java对象的生命周期中有三种状态,而且互相转化。它们分别是临时状态,持久化状态,以及游离状态。 AD:51CTO学院:IT精品课程在线看! 在Hib...

xiaml ⋅ 2014/03/30 ⋅ 0

Hibernate openSession() 与 getCurrentSession() 区别

一、getCurrentSession()与openSession()的区别 1、getCurrentSession () 使用当前的session openSession() 重新建立一个新的session 2、采用getCurrentSession()创建的session会绑定到当前线...

LYQ1990 ⋅ 2016/04/27 ⋅ 0

关于hibernate 更新或者删除报错different object with the same identifier

Hibernate 疑难异常及处理 1、a different object with the same identifier value was already associated with the session。   错误原因:在hibernate中同一个session里面有了两个相同标......

章大大 ⋅ 2016/12/23 ⋅ 0

Hibernater学习笔记(三)

1.Hibernate缓存 Hibernate一级缓存 hibernate 的一级缓存默认是打开的 hibernate的一级缓存使用范围,是session范围,从session创建到session关闭范围 hibernate的一级缓存中,储存数据必须...

Mr_欢先生 ⋅ 2017/12/08 ⋅ 0

hibernate中对象的三个状态理解

Hibernate中对象的三大状态一、transient(临时态)特点:通过new操作创建出来的对象,此时的对象未被纳入session管理,数据库中没有相对应的记录 二、persistent(持久化状态)例如:在ser...

jiefalcon ⋅ 2013/06/19 ⋅ 0

Hibernate搭建开发环境+简单实例(二)

Hibernate是非常典型的持久层框架,持久化的思想是非常值得我们学习和研究的。这篇博文,我们主要以实例的形式学习Hibernate,不深究Hibernate的思想和原理,否则,一味追求,苦学思想和原理...

architect刘源源 ⋅ 01/11 ⋅ 0

Hibernate之一级缓存和二级缓存

1:Hibernate的一级缓存:   1.1:使用一级缓存的目的是为了减少对数据库的访问次数,从而提升hibernate的执行效率;(当执行一次查询操作的时候,执行第二次查询操作,先检查缓存中是否有...

别叫小伙 ⋅ 2017/03/21 ⋅ 0

新手上路之Hibernate(三):持久化对象三种状态以及session的Get()与Load()区别

一、Hibernate持久化对象三种状态 在hibernate中持久化类的对象可以划分为三种状态,分别是瞬态,持久态,脱管态。 1. 瞬态(Transient),也叫临时态。处于这种状态的对象具备的特征如下: a)...

Airship ⋅ 2016/12/12 ⋅ 0

hibernate学习笔记-关闭session之后如何进行懒加载《二》

当在使用Hibernate做开发的时候出现org.hibernate.LazyInitializationException: could not initialize proxy - no Session 错误提示 病症:这是一个lazy使用后的Exception,使用迟时加载,在...

xiaml ⋅ 2014/04/09 ⋅ 0

Hibernate通过createSQLQuery( )方法实现增删改查

Hibernate通过createSQLQuery( )方法实现增删改查 Hibernate的三种实现方式之一:createSQLQuery( ) 一、项目结构 二、hibernate核心配置文件: hibernate.cfg.xml [java] view plain copy...

代金券优惠 ⋅ 04/16 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

ThreadPoolExecutor

ThreadPoolExecutor public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, ......

4rnold ⋅ 昨天 ⋅ 0

Java正无穷大、负无穷大以及NaN

问题来源:用Java代码写了一个计算公式,包含除法和对数和取反,在页面上出现了-infinity,不知道这是什么问题,网上找答案才明白意思是负的无穷大。 思考:为什么会出现这种情况呢?这是哪里...

young_chen ⋅ 昨天 ⋅ 0

前台对中文编码,后台解码

前台:encodeURI(sbzt) 后台:String param = URLDecoder.decode(sbzt,"UTF-8");

west_coast ⋅ 昨天 ⋅ 0

实验楼—MySQL基础课程-挑战3实验报告

按照文档要求创建数据库 sudo sercice mysql startwget http://labfile.oss.aliyuncs.com/courses/9/createdb2.sqlvim /home/shiyanlou/createdb2.sql#查看下数据库代码 代码创建了grade......

zhangjin7 ⋅ 昨天 ⋅ 0

VS2015配置并运行汇编(一步一步照图做)【vs2017的链接在最后】

x64: TITLE Add and Subtract (AddSub.asm) ; This program adds and subtracts 32-bit integers. ; Last update: 2/1/02 ;.MODEL flat,stdcall x64 not su......

simpower ⋅ 昨天 ⋅ 0

一起读书《深入浅出nodejs》-node模块机制

node 模块机制 前言 说到node,就不免得提到JavaScript。JavaScript自诞生以来,经历了工具类库、组件库、前端框架、前端应用的变迁。通过无数开发人员的努力,JavaScript不断被类聚和抽象,...

小草先森 ⋅ 昨天 ⋅ 0

Java桌球小游戏

其实算不上一个游戏,就是两张图片,不停的重画,改变ball图片的位置。一个左右直线碰撞的,一个有角度碰撞的。 左右直线碰撞 package com.bjsxt.test;import javax.swing.*;import j...

森林之下 ⋅ 昨天 ⋅ 0

你真的明白RPC 吗?一起来探究 RPC 的实质

你真的明白RPC 吗?一起来探究 RPC 的实质 不论你是科班出身还是半路转行,这么优秀的你一定上过小学语文,那么对扩句和缩句你一定不陌生。缩句就是去除各种修饰提炼出一句话的核心,而不失基...

AI9o後 ⋅ 昨天 ⋅ 0

z-index设置失效?

今天碰到了一个问题,就是在给li设置提示框的时候,有用到遮罩效果,本来想把对应的出现在最顶层,可是不管将li设置的z-index值设为多大,li都没有出现在遮罩层之上。 我在网上查了z-index设...

IrisHunag ⋅ 昨天 ⋅ 0

CyclicBarrier、CountDownLatch以及Semaphore使用及其原理分析

CyclicBarrier、CountDownLatch以及Semaphore是Java并发包中几个常用的并发组件,这几个组件特点是功能相识很容易混淆。首先我们分别介绍这几个组件的功能然后再通过实例分析和源码分析其中设...

申文波 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部