Hibernate学习(二)

目录

  1. Hibernate的持久化类介绍
  2. Hibernate持久化对象的状态
  3. Hibernate的一级缓存
  4. Hibernate的事务与并发
  5. 线程ThreadLocal绑定Session
  6. Hibernate的基本查询(HQL)

1. Hibernate持久化类

1.1 持久化类
就是普通的Java实体类,这个类通过映射文件与数据库表建立关联后就成为持久化类。

1.2 持久化类编写规则
提供无参构造函数(反射)
提供标识属性,映射数据表的主键字段
所有属性提供getter、setter方法
标识属性尽量使用基本数据类型的包装类(如Integer、Long...)

2. Hibernate持久化对象的状态

状态 描述
瞬时态(Transient Object) 没有持久化标识ID(对象刚刚创建),没有被纳入到Session对象的管理
持久态(Persistent Object) 有持久化标识ID(执行了数据库的操作,如保存或查询等),已经被纳入到Session对象的管理(持久态对象修改数据可以自动更新数据库)
脱管态(Detached Object) 有持久化标识ID,已经脱离了Session对象的管理

3. Hibernate的一级缓存

Hibernate框架提供了两种缓存:分别是一级缓存以及二级缓存,一级缓存是默认并且不可更改的,它的生命周期与session一致(session级别的缓存);二级缓存默认没有开启,需要我们手动在配置文件中添加(以后补充)是进程或集群范围内的缓存,可以在多个session中共享数据。

接下来我们编写代码,通过在同一个Session对象中进行两次查询来证明一级缓存的存在

@Test
public void twiceQueryTest()
{
    Session session = HibernateUtils.getSession();
    Transaction transaction = session.beginTransaction();

    //通过id查询一条数据
    User u1 = session.get(User.class, 1L);
    User u2 = session.get(User.class, 1L);
    //比较这两个对象的内存地址
    System.out.println(u1 == u2);

    transaction.commit();
    session.close();
}

头铁的我发现SQL只执行了一次,并且这两个对象的内存地址是相等的;这就说明了一级缓存的存在;

image

控制Session一级缓存的方法

方法 描述
Session.clear() 清空缓存
Session.evict(Object entity) 从缓存中清除指定的对象
Session.flush() 刷出缓存, 可以强制进行从内存到数据库的同步。

4. Hibernate的事务与并发

4.1 事务描述

事务就是一组不可分割的原子操作,操作要么成功要么失败,最经典的例子就是转账了

4.2 事务的特性

  • 原子性:事务不可分割
  • 一致性:事务执行的前后数据的完整性应该保持一致
  • 隔离性:一个事务执行过程中,不应该收到其他事务的干扰
  • 持久性:事务一旦提交,数据永久保存到数据库中

4.3 如果不考虑事务的隔离性,可能引发的问题

  • 脏读:A事务读到了B事务未提交的数据
  • 不可重复读:A事务读到了B事务update更新提交的数据,导致多次查询的结果不一致
  • 虚读:A事务读到了B事务插入提交的数据,导入多次查询结构不一致

4.4 Hibernate设置隔离级别

<property name="hibernate.connection.isolation">4</property>
隔离级别 描述
1 Read uncommitted isolation(未提交读;上面的问题都有可能出现)
2 Read committed isolation(已提交读;避免了脏读,其它两个问题有可能出现)
4 Repeatable read isolation(可重复读;避免了脏读、不可重复读,但是虚读有可能出现)
8 Serializable isolation(串行化;上面的问题都可以避免,但是效率较低)

4.5 Hibernate并发之数据丢失更新

场景:两个事务同时对一条数据进行操作

解决方法(2种):

  • 悲观锁

采用的是数据库提供的一种锁机制,当A事务操作数据是,会把该条数据锁起来,其它事务不能操作;只有当A事务提交后,释放锁才能进行操作。

//通过设置LockMode枚举
session.get(User.class,1L,LockMode.UPGRADE);
LockMode 描述(待补充)
NONE 默认模式
READ
UPGRADE 已过时
UPGRADE_NOWAIT
UPGRADE_SKIPLOCKED
WRITE
FORCE 已过时
OPTIMISTIC
OPTIMISTIC_FORCE_INCREMENT
PESSIMISTIC_READ
PESSIMISTIC_WRITE
PESSIMISTIC_FORCE_INCREMENT
  • 乐观锁

采用版本号的机制来解决问题,会给表添加一个字段verision,默认值为0,当A事务在操作该条数据提交时,首先会检查版本号,如果发现版本号的值相同时才可以提交事务,并且让version+1;当B事务也提交时,和前面说的一样,发现version变了,程序就会报错。

step1.在对应的JavaBean中添加一个属性,例如

private Integer version;
...
getter setter

step2.在实体类映射文件(User.hbm.xml)中提供<version>标签

<hibernate-mapping>
    <class name="com.example.hibernate.User" table="t_user">
        <id name="uid" column="uid">
            <generator class="native"/>
        </id>
        <version name="version"/>
        ...
    </class>

</hibernate-mapping>

5. 线程ThreadLocal绑定Session

在开发中我们一般在Service中处理业务(然后Service调用Dao层处理数据库操作),开启Session的事务提交;但是我们数据库的操作是放在Dao层的,这个时候Dao层想要使用Service层的Session,只能通过方法将Session作为实参传递或者使用ThreadLocal保存在线程中;Hibernate也帮我们提供了ThreadLocal的方式

step1.hibernate.cfg.xml中配置(到处都是配置,头铁)

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

step2. 使用SessionFactorygetCurrentSeesion方法获取Session对象,需要注意的是该Session对象线程结束会自动关闭,不需要我们手动调用Sessionclose方法。

...
//创建session对象
Session session = factory.getCurrentSession();
...

6. Hibernate的基本查询(HQL)

6.1 使用Query查询接口

...
//查询所有记录
Query query = session.createQuery("from User");
List<User> list = query.list();
System.out.println(list);

//条件查询,使用?占位符
Query query = session.createQuery("from User where uname = ?");
query.setString(0,"许渺");
List<User> list = query.list();
System.out.println(list);

//条件查询,使用:占位符
Query query = session.createQuery("from User where uname = :name");
query.setString("name","许渺");
List<User> list = query.list();
System.out.println(list);
...

6.2 使用Criteria查询接口(适合做条件查询)

...
//查询所有
Criteria criteria = session.createCriteria(User.class);
List<User> list = criteria.list();
System.out.println(list);

//条件查询
Criteria criteria = session.createCriteria(User.class);
criteria.add(Restrictions.eq("name", "许渺"));
List<User> list = criteria.list();
System.out.println(list);
...
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 151,688评论 1 330
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 64,559评论 1 273
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 101,749评论 0 226
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 42,581评论 0 191
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 50,741评论 3 271
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 39,684评论 1 192
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,122评论 2 292
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,847评论 0 182
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,441评论 0 228
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,939评论 2 232
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,333评论 1 242
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,783评论 2 236
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,275评论 3 220
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,830评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,444评论 0 180
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 34,553评论 2 249
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 34,618评论 2 249

推荐阅读更多精彩内容

  • 这部分主要是开源Java EE框架方面的内容,包括Hibernate、MyBatis、Spring、Spring ...
    杂货铺老板阅读 1,264评论 0 2
  • 1.主键生成策略 1.1 主键的两种类型 自然主键:把数据表中的某一业务字段作为表的主键。如一张用户表中,把用户的...
    Wizey阅读 495评论 0 3
  • 本文包括:1、Hibernate的持久化类2、Hibernate 持久化对象的三个状态(难点)3、Hibernat...
    廖少少阅读 1,389评论 0 13
  • Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库...
    兰缘小妖阅读 1,173评论 1 18
  • Hibernate: 一个持久化框架 一个ORM框架 加载:根据特定的OID,把一个对象从数据库加载到内存中OID...
    JHMichael阅读 1,928评论 0 27