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. Codeforces 610D Vika and Segments 线段树+离散化+扫描线

    可以转变成上一题(hdu1542)的形式,把每条线段变成宽为1的矩形,求矩形面积并 要注意的就是转化为右下角的点需要x+1,y-1,画一条线就能看出来了 #include<bits/stdc++ ...

  2. 64位Navicat Premium安装/破解【含资源】

    开门见山: 1/先安装Navicat Primium,双击Navicat Primium——trial_64.exe(64位) 2/安装好打开Navicat Primium,提示使用或注册时,双击Pa ...

  3. 【Oracle】实现Oracle数据库对象的一键升级

    引言     公司内部的项目比较倾向于将业务逻辑放在oracle存储过程中实现,所以每次项目升级都涉及到很多的oracle表,存储过程等数据库对象的升级.然而采取的升级方式是比较"原始&qu ...

  4. 2018-2019-2 20165210《网络对抗技术》Exp6 信息搜集与漏洞扫描

    2018-2019-2 20165210<网络对抗技术>Exp6 信息搜集与漏洞扫描 一.实验目标: 掌握信息搜集的最基础技能与常用工具的使用方法. 二.实验内容: 各种搜索技巧的应用 G ...

  5. linux C gbk utf-8编码转换

    http://blog.csdn.net/sealyao/article/details/5043138

  6. ugui Event.current.mousePosition获取的坐标原点在左上角

    脚本里使用OnGUI(),在鼠标按下时出发EventType.MouseDown事件,此时如果观察Event.current.mousePosition的坐标原点时左上角,即鼠标按下的点越靠近左上角, ...

  7. Effective Python之编写高质量Python代码的59个有效方法

                                                         这个周末断断续续的阅读完了<Effective Python之编写高质量Python代码 ...

  8. session 丢失问题

    1. 存到memcached中, 十分简单, 在使用session之前, 加入下面两行代码 int_set('session.save_handler', 'memcache'); int_set(' ...

  9. QQ帐户的申请与登陆(25 分)

    实现QQ新帐户申请和老帐户登陆的简化版功能.最大挑战是:据说现在的QQ号码已经有10位数了. 输入格式: 输入首先给出一个正整数N(≤),随后给出N行指令.每行指令的格式为:“命令符(空格)QQ号码( ...

  10. 滑雪(经典DP思想)

    个人心得:思想还是不够,开始自己写但是不知道如何记录长度,也不太知道状态的转移,后面看了百度, 发现人人为我我为人人就是一步一步推导, 而递归思想就要求学会记录和找到边界条件,这一题中的话就是用递归, ...