Hibernate 简易入门教程
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 简易入门教程的更多相关文章
- Web压力测试工具 LoadRunner12.x简易入门教程--(一)回放与录制
LoadRunner12.x简易入门教程--(一)回放与录制 今天在这里分享一下LoadRunner12.x版本的入门使用方法,希望对刚接触LoadRunner的童鞋有所帮助. LoadRun ...
- Pytest自动化测试-简易入门教程(02)
Pytest框架简介 Pytest是一个非常成熟的全功能的Python测试框架,主要有以下几个特点:1.简单灵活,容易上手,支持参数化2.能够支持简单的单元测试和复杂的功能测试,3.还可以用来做sel ...
- Lua简易入门教程
环境:lua for windows (lfW)主页:http://luaforwindows.luaforge.net/https://code.google.com/p/luaforwindows ...
- Webpack简易入门教程
<!-- 其实网上关于webpack的教程已经很多了,但是本人在学习过程中发现很多教程有错误,或者写的很不全面,结果做的过程出现各种各样的问题,对新手不但不友好还会让人浪费很多不必要的时间.所以 ...
- 给萌新的Flexbox简易入门教程
转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 原文出处:https://www.sitepoint.com/flexbox-css-flexible-bo ...
- hibernate简单入门教程(一)---------基本配置
应用级别所以很粗浅 首先介绍一下hibernate框架: 1.优秀的持久化(通俗讲把内存上的短时间运行信息存储在持久化硬盘上)框架. 2.作用于持久层,因为没什么侵入性,所以同样适用于其他层面上的存储 ...
- Pytest自动化测试-简易入门教程(01)
我们今天主讲的内容,就是测试框架Pytest,讲到这个测试框架对于没有做过Web自动化的伙伴来说,会觉得这个东西是陌生的,那么到底什么是框架呢?什么又是自动化呢?自动化为什么又要用框架呢? 难道我学自 ...
- mac os x使用Git简易入门教程
具体如下: 1, 首先要了解什么是Git. 简而言之,Git是一个分布式的代码版本管理工具.类似的常用工具还有SVN,CVS. 概念了解参见:http://baike.baidu.com/subvie ...
- 【记录】YAML 简易入门教程
YAML 是 "YAML Ain't a Markup Language"(YAML 不是一种标记语言)的递归缩写.在开发的这种语言时,YAML 的意思其实是:"Yet ...
随机推荐
- uva 10739 dp
https://vjudge.net/problem/UVA-10739 和昨天的那个回文串几乎一样只是加了条件限制,可以随意增删以及替换. #include<iostream> #inc ...
- jar包作用
hibernate中jar包的作用 (1)hibernate3.jar:Hibernate的核心库,没有什么可说的,必须使用的jar包 (2)cglib-asm.jar:CGLIB库,Hibernat ...
- NAVICAT PREMIUM 初识
1 问题运行SQL取数语句出错?. 答案:因为运行SQL文件时没有这个表.新的数据库里面 解决方法: 获取需要建立的二维表创建语句 新建查询 输入语句,点击运行即可 解释注释语句: 主体为五个字段的主 ...
- LINUX下SYN FLOOD攻击及LINUX下SYN攻防简述
LINUX下SYN攻防战如下 (一)SYN攻击原理 SYN攻击属于DOS攻击的一种,它利用TCP协议缺陷,通过发送大量的半连接请求,耗费服务器CPU和内存资源.SYN攻击聊了能影响主机外,还可以危害路 ...
- svn默认地址老发生改变,记下默认路径
C:\Users\Administrator\AppData\Roaming\Subversion
- 剑指offer--8.调整数组顺序使奇数位于偶数前面
习惯了简单 ------------------------------------------------- 时间限制:1秒 空间限制:32768K 热度指数:422906 本题知识点: 数组 题目 ...
- BZOJ - 4196 软件包管理器 (树链剖分+dfs序+线段树)
题目链接 设白色结点为未安装的软件,黑色结点为已安装的软件,则: 安装软件i:输出结点i到根的路径上的白色结点的数量,并把结点i到根的路径染成黑色.复杂度$O(nlog^2n)$ 卸载软件i:输出结点 ...
- Codeforces 786B. Legacy 线段树+spfa
题目大意: 给定一个\(n\)的点的图.求\(s\)到所有点的最短路 边的给定方式有三种: \(u \to v\) \(u \to [l,r]\) \([l,r] \to v\) 设\(q\)为给定边 ...
- object.observe数据绑定
object.observe方法格式如下: object.observe(object,callback) 监听object对象,当该对象有新增或更新或删除等操作,就会触发callback,就实现了双 ...
- Sqoop-从hive导出分区表到MySQL
经多次验证,发现并没有特殊的方法能够直接把多个分区一次性读入,并插入MySQL的方法,以后发现会在此添加. Sqoop只提供了从MySQL导入到HIVE分区表的相关参数,反向并无特别参数. 从HIVE ...