javaSE面试知识点Java@IT·互联网

震惊!从未见过如此简单粗暴的Hibernate教程

2017-02-06  本文已影响2024人  肥朝
内容大纲.png

引题

对象关系映射(Object Relational Mapping,简称ORM)是一种为了解决面向对象与关系数据库存在的互不匹配的现象的规范,简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将java程序中的对象自动持久化到关系数据库中.

面向对象概念 面向关系概念
对象 表的行(记录)
属性 表的列(字段)

ORM框架在前后端领域都能看到它的影子,比如Android的greenDAO,比如iOS的coreData,比如Node.js的mongoose,这里主要讲解Java中Hibernate我们比较容易忽略和重要的点,如想了解greenDAO、coreData、mongoose的可以留言

save和get的执行流程

save和get.png

save:

get:

get和load方法的区别

先看这段简单的测试代码

@Test
public void testGetAndLoad() {

    Session session = HibernateUtil.getSession();
    session.beginTransaction();
    //立即发sql
    //Person p = (Person) session.get(Person.class, 1L);

    Person p = (Person) session.load(Person.class, 2L);
    session.getTransaction().commit();
    //预加载延迟加载对象
    //Hibernate.initialize(p);

    //当查询一个不存在的对象时,依然返回不为null(注意,打印对象会调用toString方法)
    System.out.println(p == null);
    session.close();
}

持久化对象的生命周期

为什么需要关注持久化对象的生命周期?那我们来回忆使用Hibernate中是否遇到的三个问题

那么SQL的执行时机和什么有关系呢?和对象的状态有关系.那持久化对象的状态有哪一些?怎么划分的?

划分的规则:

状态 描述 特点
临时状态/瞬时态(transient) 刚刚用new语句创建,没有被持久化,不处于session中 没有oid,不在session当中
持久化状态(persistent) 已经被持久化,加入到session的缓存中 有oid,在session当中
游离状态(detached)/脱管态 已经被持久化,但不处于session中 有oid,不在session当中
删除状态(removed) 对象有关联的ID,并且在session管理下,但是已经计划被删除 有oid,在session当中,最终的效果是被删除.
持久化对象的状态.png

对象状态的总结

session中的方法仅仅只是改变对象的状态,不负责发送SQL/默认情况下事务提交的时候发送SQL,那么之前是三个问题就可以迎刃而解了.

二级缓存

要了解二级缓存,我们就必须知道一级缓存是什么.介绍一级缓存之前,我们先回顾一下Session

session

public void testSession() {
    Session session = HibernateUtil.getSession();
    //只打印一条SQL
    User user = (User) session.get(User.class, 1L);
    User user1 = (User) session.get(User.class, 1L);
}

原理如图:

一级缓存.png

虽然一级缓存可以提高性能,但是由于session的作用域有限,因此,提高的性能也是非常有限的.所以这就引出了二级缓存的概念

二级缓存

若想了解HibernateMybatis的缓存对比可以戳这里Hibernate和Mybaitis缓存

事务并发问题

事务并发时,会产生两类丢失更新问题,如图

第一类丢失更新问题.png 第二类丢失更新问题.png

然而解决的办法有两个,一个称之为悲观锁,一个称之为乐观锁

悲观锁(Pessimistic Lock): 悲观地认为每次自己去拿数据的时候别人会修改数据,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁。底层采用的就是SELECT ..... FOR UPDATE

//查询的时候
session.get(User.class,1L,LockOptions.UPGRADE);
//SQL: SELECT * FROM t_person WHERE id = 1 FOR UPDATE;
//悲观锁:效率低,容易造成死锁,我们一般使用乐观锁.
悲观锁.png

乐观锁(Optimistic Lock): 乐观地认为每次去拿数据的时候别人不会修改数据,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。

乐观锁.png

在hibernate中使用乐观锁,推荐使用version方式:

//1.给对象添加一个int version字段,最好设置属性为private;
//2.在mapping文件中添加<version>元素即可;
<class name="Employee">
    <version name="version"/>
    ...
</class>
//3.剩下的Hibernate帮我们管理
上一篇下一篇

猜你喜欢

热点阅读