Hibernate

HIbernate主要包含如下几个接口:Session,Query,Criteria以及Transaction。这些接口的实现在幕后是紧密相连的。

在一个HIbernate应用程序中,通过实质上改变他们的状态来保存和加载对象,我们在工作单元中进行这项工作。单个工作单元是一组被认为是原子团的操作。

1、开始工作单元

		Session session1 = factory.openSession();
Transaction tx1 = session1.beginTransaction();

 一个新的持久化上下文被初始化了并同时开始了一个事务,它将管理这个session中所有的对象。如果需要访问多个数据库就会有多个sessionfactory对象

sessionfactory对象的创建十分昂贵,所以不应该针对同一个数据库连接重复创建sessionfactory对象。

2、持久化对象

		Message item = new Message();
Serializable itemId = session1.save(item);
tx1.commit();
session1.close();

  调用save()使得瞬时对象item变成了持久化,同时调用commit()时对持久化对象所做的变化与数据库进行了同步,hibernate获得了一个jdbc连接,并执行sql insert语句。save()函数将返回持久化实例的数据库标识符(取决于自己配置的标识符生成器)。

  session最终被close()方法关闭,item引用处于脱管状态。

  如果在事务发生期间发生异常了,hibernate对持久化对象所做的所有变化将进行数据库级别的回滚。要注意的是,hibernate将不会把内存变化会滚到持久化对象。因此需要放弃失败的session。

3、获取持久化对象

  

		Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction(); Object item = session.get(Message.class, new Long(1234)); tx.commit();
session.close();

  hibernate提供了get、load两种方法通过标识符获取持久化对象。获取到的对象处于持久化状态,一旦持久化上下文关闭,该对象将处于脱管状态。

  get和load的一个区别在于当无法找到给定标识符关联的对象时,get()方法返回一个null而load()方法将抛出ObjectNotFoundException。

  更重要的是load()方法始终试图返回一个代理,即不发生数据库命中而get()方法从不返回代理,每一次都将命中数据库。

4、修改持久化对象

  对持久化实例进行修改,当事务的commit()被调用时,所做的修改将被传播到数据库。这种机制叫做自动脏检查(意味着hibernate追踪并保存在持久化状态中对一个对象所作出的改变)。

5、使持久化对象变成瞬时对象

  

		Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction(); Message item = new Message();
item.setText("msg1");
Serializable itemId = session.save(item); Object obj = session.load(Message.class, (Long)itemId);
session.delete(obj); tx.commit();
session.close();

  调用delete()之后,这个对象处于移除状态(removed),此时不应该再继续使用它。commit()后,执行SQL DELETE操作。Session关闭后,该对象被认为是一个普通的瞬时实例。最终将被垃圾回收器收回。

  如果启用了hibernate.use_identifier_rollback配置选项,hibernate会在删除后设置被删除的对象的标识符属性为NULL,成为一个可以在后期被复用的干净瞬时实例。

6、复制对象

  当需要从一个数据库获取对象并把它们保存在另一个数据库中的时候。这称做对象的复制。

  

        Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Message item = new Message();
Serializable itemId = session.save(item);
Message theItem = (Message) session.get(Message.class, itemId);
tx.commit();
session.close(); Session session2 = sessionFactory2.openSession();
Transaction tx2 = session2.beginTransaction();
session2.replicate(item, ReplicationMode.LATEST_VERSION);
tx2.commit();
session2.close();

  ReplicationMode参数说明:

  ReplicationMode.IGNORE:当现有的数据库行包含与目标数据库中相同的标识符时忽略对象。

  ReplicationMode.OVERWRITE:覆盖任何包含与目标数据库中相同标识符的现有数据库行。

  ReplicationMode.EXCEPTION:如果现有的数据库行包含与目标数据库中相同的标识符时抛出异常。

  ReplicationMode.LASTEST_VERSION:如果目标数据库的版本对对象早则覆盖,否则忽略。

使用脱管对象

1、重附被修改的脱管实例

        Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Message item = new Message();
Serializable itemId = session.save(item);
Message theItem = (Message) session.get(Message.class, itemId);
tx.commit();
session.close(); theItem.setText("hello"); Session session2 = sessionFactory.openSession();
Transaction tx2 = session2.beginTransaction();
session2.update(theItem);
tx2.commit();
session2.close();

  这里有一个需要注意的地方是 当设置select-before-update="true"时,hibernate在update前将进行select检查是否有属性发生了变化(即是否为脏对象) 否则将不执行update操作

2、使托管对象变成瞬时

        Session session2 = sessionFactory.openSession();
Transaction tx2 = session2.beginTransaction();
session2.delete(theItem);
tx2.commit();
session2.close();

  调用delete函数内部进行了两步操作,首先将对象重附到session,再对该对象进行删除操作。托管对象的重附是在几个session中间传输数据的唯一可行方法。

3、合并脱管对象的状态

  

        Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Message item = new Message();
Serializable itemId = session.save(item);
Message theItem = (Message) session.get(Message.class, itemId);
tx.commit();
session.close(); Session session2 = sessionFactory.openSession();
Transaction tx2 = session2.beginTransaction(); Message item2 = (Message) session2.get(Message.class, itemId);
session2.update(item); tx2.commit();
session2.close();

  尝试运行如上代码将会抛出异常:A different object with the same identifier value was already associated with the session。Hibernate无法确定哪个对象表示当前状态。

  

        Session session2 = sessionFactory.openSession();
Transaction tx2 = session2.beginTransaction(); Message item2 = (Message) session2.get(Message.class, itemId);
Message item3 = (Message) session2.merge(item);
System.out.println(item == item2);  //false
System.out.println(item == item3);  //false
System.out.println(item2 == item3);  //true session2.update(item);
  
tx2.commit();

          session2.close();

 

  调用merge()函数内部进行了如下几个动作:

  1、HIbernate检查当前持久化上下文中的持久化实例是否具有与正在合并的脱管实例相同的数据库标识符。

  2、如果有找到相同标识符的持久化实例,HIbernate把脱管实例的状态复制到持久化实例中去。

  3、如果持久化上下文中没有相等的持久化实例,HIbernate就从数据库中加载他,然后将脱管状态对象及被获取的对象进行合并。

  4、如果在数据库中也没有找到相等标识符的实例,就会创建新的持久化实例并将被合并的实例复制到新的持久化实例上,最后插入到数据库中并通过merge返回。

  5、如果传递到merge函数中的是一个瞬时实例,而不是脱管对象,也会发生插入。

JPA

1、持久化实体实例

        EntityManagerFactory emf =
Persistence.createEntityManagerFactory("helloworld");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin(); Message item = new Message();
item.setText("XXXX");
em.persist(item); tx.commit();
em.close();

注意:persist不会返回实体实例的数据库标识符。Session也实现了persist方法 但是Session不会把persist()操作级联到被关联的实体和集合,只是被级联到调用persist()可以到达的实体。

2、获取实体实例

        EntityManager em2 = emf.createEntityManager();
EntityTransaction tx2 = em2.getTransaction();
tx2.begin(); Message finded = em2.find(Message.class, new Long(1));
     Message finded2 = em2.getReference(Message.class, new Long(1111));
tx2.commit();
em2.close();

find函数始终命中数据库,如果找不到包含指定标识符的持久化实例,find就返回null。

getRerence函数始终不会命中数据库, 且当没有找到指定标识符实例时将抛出异常

3、修改持久化的实体实例

Java Persistence在事务提交后执行与数据库的同步.等同于HIbernate session提供的自动脏检查

4、使持久化实体实例变成瞬时

Java Persistence的remove方法语义和HIbernate Session中的delete()方法相同。但是要注意的是,不能对脱管状态的实体进行remove操作 否则会抛出异常。必须先合并脱管实例,再移除被合并的对象。

5、清除持久化上下文

对持久化实体实例所做的所有修改都在某个时间点与数据库同步, 这个过程称做清除。

每当EntityTransaction中的Commit被调用时,就清除EntityManager的持久化上下文。但是JPA实现被允许在其他的时间点上与持久化上下文同步

HIbernate作为一个JPA同步,在下列时间点同步:

EntityTransaction被提交时

执行查询时

当应用程序显式地调用flush()时

Hibernate 简易入门教程的更多相关文章

  1. Web压力测试工具 LoadRunner12.x简易入门教程--(一)回放与录制

        LoadRunner12.x简易入门教程--(一)回放与录制 今天在这里分享一下LoadRunner12.x版本的入门使用方法,希望对刚接触LoadRunner的童鞋有所帮助. LoadRun ...

  2. Pytest自动化测试-简易入门教程(02)

    Pytest框架简介 Pytest是一个非常成熟的全功能的Python测试框架,主要有以下几个特点:1.简单灵活,容易上手,支持参数化2.能够支持简单的单元测试和复杂的功能测试,3.还可以用来做sel ...

  3. Lua简易入门教程

    环境:lua for windows (lfW)主页:http://luaforwindows.luaforge.net/https://code.google.com/p/luaforwindows ...

  4. Webpack简易入门教程

    <!-- 其实网上关于webpack的教程已经很多了,但是本人在学习过程中发现很多教程有错误,或者写的很不全面,结果做的过程出现各种各样的问题,对新手不但不友好还会让人浪费很多不必要的时间.所以 ...

  5. 给萌新的Flexbox简易入门教程

    转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 原文出处:https://www.sitepoint.com/flexbox-css-flexible-bo ...

  6. hibernate简单入门教程(一)---------基本配置

    应用级别所以很粗浅 首先介绍一下hibernate框架: 1.优秀的持久化(通俗讲把内存上的短时间运行信息存储在持久化硬盘上)框架. 2.作用于持久层,因为没什么侵入性,所以同样适用于其他层面上的存储 ...

  7. Pytest自动化测试-简易入门教程(01)

    我们今天主讲的内容,就是测试框架Pytest,讲到这个测试框架对于没有做过Web自动化的伙伴来说,会觉得这个东西是陌生的,那么到底什么是框架呢?什么又是自动化呢?自动化为什么又要用框架呢? 难道我学自 ...

  8. mac os x使用Git简易入门教程

    具体如下: 1, 首先要了解什么是Git. 简而言之,Git是一个分布式的代码版本管理工具.类似的常用工具还有SVN,CVS. 概念了解参见:http://baike.baidu.com/subvie ...

  9. 【记录】YAML 简易入门教程

    YAML 是 "YAML Ain't a Markup Language"(YAML 不是一种标记语言)的递归缩写.在开发的这种语言时,YAML 的意思其实是:"Yet ...

随机推荐

  1. 解决:AttributeError: module 'requests' has no attribute 'get'”

    今天学习Requests库,当用pip install requests安装后,写了一段代码报错:AttributeError: module 'requests' has no attribute ...

  2. 去除编译警告@SuppressWarnings注解用法详解(转)

    使用:@SuppressWarnings(“”)@SuppressWarnings({})@SuppressWarnings(value={}) 编码时我们总会发现如下变量未被使用的警告提示: 上述代 ...

  3. Maven下载 || 配置本地仓库 || IntelliJ IDEA配置Maven教程

    本文章主要介绍1.Maven下载   2.配置本地仓库Repository   3.IDEA配置Maven 三点. 相关博客: Eclipse配置Maven https://www.cnblogs.c ...

  4. RNN、LSTM、Char-RNN 学习系列(一)

    RNN.LSTM.Char-RNN 学习系列(一) zoerywzhou@gmail.com http://www.cnblogs.com/swje/ 作者:Zhouw  2016-3-15 版权声明 ...

  5. fastadmin学习文档

    https://doc.fastadmin.net/docs/index.html 介绍 FastAdmin是一款基于ThinkPHP5+Bootstrap的极速后台开发框架. 主要特性 基于Auth ...

  6. Node.Js and Mongoose

    Mongoose官方API,我做完之后整理出来的心得. ONE· Getting Started First be sure you have MongoDB and Node.js installe ...

  7. 10个 NPM 使用技巧

    对于一个项目,常用的一些npm简单命令包含的功能有:初始化一个文件夹( npm init ),下载npm模块( npm install ),创建测试( npm tese ) 和自定义脚本( npm r ...

  8. 获取url参数并且中文不乱码的方法

    function getUrlArgument(name) { var reg = new RegExp("(^|&)" + name + "=([^&] ...

  9. HIVE-执行distribute by时报错的解决过程---之如何分析hive执行的错误并解决

    在执行一条HIVE语句的时候报了以下错误,重新检查了所有步骤,重启所有服务,发现没有问题. 但发现一个有趣的事情 1,select sno,sname,sex,sage,sdept from stud ...

  10. bzoj 3907 网格 bzoj2822 [AHOI2012]树屋阶梯——卡特兰数(阶乘高精度模板)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3907 https://www.lydsy.com/JudgeOnline/problem.p ...