Hibernate对象的状态
站在持久化的角度, Hibernate 把对象分为 4 种状态:
1. 持久化状态
2. 临时状态
3. 游离状态
4. 删除状态
Session 的特定方法能使对象从一个状态转换到另一个状态.
下面是各状态之间的转换图, 以及如何转换的:

准备工作:
1. 建立持久化类
Person类
package com.hibernate.entities;
public class Person {
private Integer id;
private String name;
private Integer age;
public Person() {
super();
}
public Person(String name, Integer age) {
super();
this.name = name;
this.age = age;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
2. 建立持久化类的映射文件
Person.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.hibernate.entities.Person" table="PERSONS">
<id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="identity" />
</id>
<property name="name" type="java.lang.String">
<column name="NAME" />
</property>
<property name="age" type="java.lang.Integer">
<column name="AGE" />
</property>
</class>
</hibernate-mapping>
3. 建立Hibernate的主配置文件 hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- 配置连接数据库的信息 -->
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">oracle</property>
<property name="hibernate.connection.url">jdbc:mysql:///hibernate</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<!-- 配置数据库方言 -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQL57InnoDBDialect</property>
<!-- 设置数据表生成策略 -->
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- 是否格式化SQL -->
<property name="hibernate.format_sql">true</property>
<!-- 是否显示SQL -->
<property name="hibernate.show_sql">true</property>
<!-- 修改delete()的默认行为, 使删除对象的OID变为null -->
<property name="hibernate.use_identifier_rollback">true</property>
<!-- 添加配置文件 -->
<mapping resource="com/hibernate/entities/Person.hbm.xml"/>
</session-factory>
</hibernate-configuration>
4. 建立单元测试类
package com.test;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.annotations.SelectBeforeUpdate;
import org.hibernate.cfg.Configuration;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class TestHibernate {
private SessionFactory sessionFactory;
private Session session;
private Transaction transaction;
@Before
public void init(){
sessionFactory = new Configuration().configure().buildSessionFactory();
session = sessionFactory.openSession();
transaction = session.beginTransaction();
}
@After
public void distory(){
transaction.commit();
session.close();
sessionFactory.close();
}
}
这里我直接把注释, 说明等文字写在代码里了,可以直接复制下来, 放到IDE开发工具里面慢慢看
package com.test;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.annotations.SelectBeforeUpdate;
import org.hibernate.cfg.Configuration;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.hibernate.entities.Person;
public class TestHibernate {
private SessionFactory sessionFactory;
private Session session;
private Transaction transaction;
@Before
public void init(){
sessionFactory = new Configuration().configure().buildSessionFactory();
session = sessionFactory.openSession();
transaction = session.beginTransaction();
}
@After
public void distory(){
transaction.commit();
session.close();
sessionFactory.close();
}
/*
* 站在持久化的角度:
* Hibernate 把对象分为 4 种状态:
* 持久化状态, 临时状态, 游离状态, 删除状态.
* Session 的特定方法能使对象从一个状态转换到另一个状态.
*/
/*
* 一: 临时对象(Transient)
* 1. 在使用代理主键的情况下, OID 通常为 null
* 2. 不处于 Session 的缓存中
* 3. 在数据库中没有对应的记录
*/
/*
* 二: 持久化对象(也叫"托管")(Persist)
* 1. OID 不为 null.
* 2. 位于Session缓存中.
* 3. 若在数据库中已经有和其对应的记录, 持久化对象和数据库中的相关记录对应.
* 4. Session在flush缓存时, 会根据持久化对象的属性变化, 来同步更新数据库.
* 5. 在同一个Session实例缓存中, 数据库表中的每条记录只对应唯一的持久化对象.
*/
/*
* 三: 删除对象(Removed)
* 1. 在数据库中没有和其OID对应的记录.
* 2. 不再处于Session缓存中.
* 3. 一般情况下, 应用程序不再使用该对象.
*/
/*
* 四: 游离对象(也叫"托管")(Detached)
* 1. OID不为null.
* 2. 不再处于Session缓存中.
* 3. 一般情况下, 游离对象是持久化对象转变过来的, 因此在数据库中可能还存在与它对应的记录.
*/
/**
* save()方法:使一个临时对象转变为持久化对象.
* 执行save()方法时, 系统会完成以下操作:
* 1. 把 new 对象加入到Session缓存中, 使它进入持久化状态.
* 2. 选用映射文件指定的标示符生成器, 为持久化对象分配唯一的OID.
* 在使用中代理主键的情况下, setId() 方法为 new 对象设置的OID 是无效的.
* 3. 计划执行一条 insert 语句(在flush缓存的时候).
* persist()方法: 同save()方法.
*/
@Test
public void testSaveOrPersist(){
// 保存一个对象
// Person person = new Person("Tom", 12);
// session.save(person);
// 使用 save() 保存一个有id值的对象时, 正常保存.
// Person person = new Person("Tom", 12);
// person.setId(100);
// session.save(person);
// 使用 persist()保存一个有id值得对象时, 抛异常!
// Person person = new Person("Mike", 23);
// person.setId(100);
// session.persist(person);
// 试图修改持久化对象的 ID, 不允许!
// Person person = session.get(Person.class, 1);
// person.setId(1000);
// session.update(person);
}
/**
* get() 和 load() 方法
* 相同点:
* 都可以根据指定的OID, 从数据库中加载一个持久化对象.
* 不通电:
* 1. 当数据库不存在OID对应的记录时:
* load() 会抛出异常.
* get() 返回null.
* 2. 两者采用不同的加载策略:
* load() 支持延迟加载.
* get() 不支持.
*/
@Test
public void testGetOrLoad(){
// 1. 使用 get() 获取对象
// 当调用 get() 时, Hibernate会计划执行SQL, 在flush时的时候, 会发送SQL语句.
// session.get(Person.class, 2);
// session.flush();
// System.out.println("======================");
// 2. 使用 load() 延迟加载对象
// 当调用 load() 时, Hibernate不会计划执行SQL
// 即使flush操作的时候, 如果没有使用这个对象, 那么Hibernate就不会发送SQL语句.
// 只有在使用这个对象的时候, Hiberante才会发送SQL语句. 这就是延迟加载!
Person person = session.load(Person.class, 2);
session.flush();
System.out.println("======================");
System.out.println(person.getName());
}
/**
* 1. update(): 使一个游离对象转变为持久化对象, 并且计划执行一条SQL语句.
* 2. 如果希望Session仅当修改了 new 对象的属性时, 才执行 update 语句
* 可以把映射文件中的<class>元素的 select-before-update 设置为true, 默认为false.
* 3. 当 update() 关联一个游离对象时, 如果在Session的缓存中已经存在相同OID的持久化对象, 会抛异常!
* 4. 当 update() 关联一个游离对象时, 如果在数据库中不存在相应的记录, 也会抛出异常!
*/
@Test
public void testUpdate(){
// 一: 正常的 update
// // tip:游离对象是由持久化对象转换过来的.
// Person person = session.get(Person.class, 1);
// transaction.commit();
// // session 关闭后, person 对象转换为游离对象.
// session.close();
// session = sessionFactory.openSession();
// transaction = session.beginTransaction();
// person.setAge(19);
// // 执行完 update, person对象由游离对象转变为持久化对象.
// session.update(person);
// 二: 当在配置文件添加 select-before-update=true 的时候
// 这里我们用注释来做, 在类上加上: @SelectBeforeUpdate(value=true)
// 1. 没有改变任何属性, 当时Hibernate仍然发送一条SQL语句来验证属性值是否改变.
// Person person = session.get(Person.class, 1);
// session.update(person);
// 2. 改变了属性之后, 不仅发送一条SQL语句, 还会发送一条update语句.
// Person person = session.get(Person.class, 1);
// person.setName("Kim");
// session.update(person);
// 三: Session缓存中存在相同的OID.
// // 先获取一个持久化Person, 然后关闭Session变为游离态.
// Person person1 = session.get(Person.class, 1);
// transaction.commit();
// session.close();
// session = sessionFactory.openSession();
// transaction = session.beginTransaction();
// // 开启Session, 再获取一个相同的Person对象
// Person person2 = session.get(Person.class, 1);
// person1.setName("Sunny");
// // 把游离态的person1转化为持久化态, 由于我们缓存中已经有一个OID为1的person2
// // 所以抛异常!(Hibernate不允许缓存中存在OID相同的对象)
// session.update(person1);
// 四: 数据库中不存在相应的记录
// 意味着这是一个临时对象, 或者删除对象
// 只能执行save()或者persist()进行持久化
// update() 只能把游离对象, 转化为持久化对象
// Person person = new Person("Lily", 15);
// // 抛异常!
// session.update(person);
}
/**
* saveOrUpdate(): 包含了 save() 和 update() 的功能
* 如果是一个临时对象, 就执行save()
* 如果是一个持久化对象, 就执行update()
* 判断是临时对象的标准:
* 1. 如果对象的OID为null.
* 2. 映射文件中<id> 设置了 unsaved-value 属性,
* 并且java对象的OID取值与这个unsaved-value属性值匹配.
*/
@Test
public void testSaveOrUpdate(){
// id(OID)值为null, 执行 insert 语句
// Person person = new Person("Mike", 15);
// session.saveOrUpdate(person);
// id(OID)值为unsaved-value的值(100), 执行insert语句
// Person person = new Person("Mike", 15);
// person.setId(100);
// session.saveOrUpdate(person);
// 数据库中有与id(OID)值对应的值, 那么就执行update语句
Person person = new Person("Mike", 15);
// 数据库中有主键为2的数据, 执行update语句
person.setId(2);
session.saveOrUpdate(person);
}
/**
* merge()
*/
@Test
public void testMerge(){
/*
* 一: 临时对象
* 创建一个新的News对象,把new1对象的属性拷贝到新建的News对象中
* 持久化这个News对象,计划执行一条insert语句
*/
// Person person = new Person("Tom", 13);
// // 发送了一条insert
// session.merge(person);
/*
* 二: 游离对象 + 存在Session缓存中
*/
// Person person1 = session.get(Person.class, 1);
// // guanbiSession, 开启Session使对象变为游离态
// transaction.commit();
// session.close();
// session = sessionFactory.openSession();
// transaction = session.beginTransaction();
// // 重新加载到Session缓存中.
// Person person2 = session.get(Person.class, 1);
// person1.setName("Mike");
// // 把person1对象的属性拷贝到person2持久化对象中,计划执行一条update语句
// // 发送了2条select, 1条update
// session.merge(person1);
/*
* 三: 游离对象 + 不存在Session缓存中 + 数据库中存在id为1的记录
*/
// Person person = session.get(Person.class, 1);
// transaction.commit();
// session.close();
// session = sessionFactory.openSession();
// transaction = session.beginTransaction();
// person.setName("Kim");
// // 从数据库加载id为1的News持久化对象(会发送一条select)
// // 把person对象的属性拷贝到News持久化对象中,计划执行一条update语句
// // 发送了2条select, 1条update
// session.merge(person);
/*
* 四: 游离对象 + 不存在Session缓存中 + 数据库中不存在id为1的记录
*/
// // 1 条select
// Person person = session.get(Person.class, 1);
// // 从数据库中删除, 1 条delete
// session.delete(person);
// transaction.commit();
// session.close();
// session = sessionFactory.openSession();
// transaction = session.beginTransaction();
// // 1 一条insert
// session.merge(person);
}
/**
* delete(): 既可以删除一个游离对象, 也可以删除一个持久化对象
* 处理过程:
* 1. 计划执行一条 delete 语句
* 2. 把对象从 Session缓存中移除, 该对象进入删除状态
* hibernate.use_identifier_rollback 属性:
* 这个值默认为false, 如果改为true, 将改变 delete()的运行行为,
* delete()会把持久化对象或游离对象的OID置为null, 使它们变为临时对象
*/
@Test
public void testDelete(){
// 1. hibernate.use_identifier_rollback=false
// Person person = session.get(Person.class, 3);
// session.delete(person);
// session.flush();
// // 打印 3
// System.out.println(person.getId());
// 2. hibernate.use_identifier_rollback=true
Person person = session.get(Person.class, 3);
session.delete(person);
session.flush();
// 打印 null
System.out.println(person.getId());
}
}
Hibernate对象的状态的更多相关文章
- Hibernate对象的状态和映射
一. Hibernate对象的状态 实体对象的三种状态: 1) 暂态(瞬时态)(Transient)---实体在内存中的自由存在,它与数据库的记录无关. po在DB中无记录(无副本),po和sessi ...
- Hibernate(3)——实例总结Hibernate对象的状态和ThreadLoacl封闭的session
俗话说,自己写的代码,6个月后也是别人的代码……复习!复习!复习!涉及的知识点总结如下: Hibernate的内部执行过程(CRUD) 对象的状态及其转换图和例子 使用JUnit测试 使用getCur ...
- Hibernate对象的状态分类
对象的状态: 临时状态Transient: 与数据库没有对应,跟Session没有关联 一般是新new出的对象 持久化状态Persistent: 对象在Session的管理之中,最终会有对应的数据库记 ...
- Hibernate对象的状态转换
Hibernate中的实体对象可以分为三种状态:Transient(临时).Persistent(持久).Detached(游离) Transient 用new创建出对象,这些对象还没有与数据库发生任 ...
- hibernate对象的状态以及生命周期
瞬时状态:session中没有,数据库中没有 持久状态:session中有,数据库中有 游离状态:session中没有,数据库中有 get和load都是用来提取数据的 get和load的区别: get ...
- 菜鸟学SSH(八)——Hibernate对象的三种状态
前面写了几篇关于SSH的博客,但不是Struts就是Spring,Hibernate还从来没写过呢.说好是SSH的,怎么可以光写那两个,而不写Hibernate呢对吧.今天就先说说Hibernate对 ...
- hibernate对象的三种状态
对于hibernate,我想不在这里讲解了,我们就直接进入主题 在这里我将要说的是"hibernate对象的三种状态",对象是我们十分熟悉的,对吧!而对于对象它有三种状态 分别是瞬 ...
- hibernate对象三种状态
在Hibernate中,对象有三种状态:临 时状态(Transient).持久状态(Persistent)和游离状态(Detached). 处于持久态的对象也称为 PO(PersistenceObje ...
- [原创]java WEB学习笔记79:Hibernate学习之路--- 四种对象的状态,session核心方法:save()方法,persist()方法,get() 和 load() 方法,update()方法,saveOrUpdate() 方法,merge() 方法,delete() 方法,evict(),hibernate 调用存储过程,hibernate 与 触发器协同工作
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
随机推荐
- 看啦这么就别人的博客 我也来写一篇! Object转换其他类型
package com.sinitek.framework.util; import java.math.BigDecimal;import java.sql.Timestamp;import jav ...
- ibatis批量操作补充
ibatis批量操作 这文章的补充吧. review代码的时候发现一个页面应用排序设置功能,原先代码中,进行了循环update实现.虽然应用较少,不过无谓浪费数据库链接实在不是一个好的想法. 所以, ...
- [Mac]关闭所有打开finder
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px 'Helvetica Light'} span.Apple-tab-span {white-sp ...
- IT行业的正式入门
虽然我是计算机专业毕业的大学生,但我自己认为我连什么是 IT都不了解,我热爱Java程序的设计,所以我现在在努力学习,今天是上Java程序设计的第一天,我正式进入IT业,踏上了这条“不归路”.figh ...
- rabin 素性检验 随机化算法
#include <cstdio> #include <cstdlib> #include <ctime> typedef long long int LL; in ...
- ✡ leetcode 157. Read N Characters Given Read4 利用read4实现read --------- java
The API: int read4(char *buf) reads 4 characters at a time from a file. The return value is the actu ...
- server.transfer 用法
server.transfer 特点: 1:大家熟悉的一个特点,用server.transfer 跳转到新页面时,浏览器的地址是没有改变的(因为重定向完全在服务器端进行,浏览器根本不知道服务器已经执行 ...
- Oracle调整联机日志大小
近期一个项目反馈月底高峰期时系统整体性能下降,抓取对应的AWR和ASH查看,等待事件排第一位的竟然是redo日志切换.进一步看每秒的日志量是5M多,而日志文件大小仅有200M.建议项目上调整日志大小, ...
- jQuery中.bind() .live() .delegate() .on()的区别
bind(type,[data],fn) 为每个匹配元素的特定事件绑定事件处理函数 $("a").bind("click",function(){alert(& ...
- List<T>线性查找和二分查找BinarySearch效率分析
今天因为要用到List的查找功能,所以写了一段测试代码,测试线性查找和二分查找的性能差距,以决定选择哪种查找方式. 线性查找:Contains,Find,IndexOf都是线性查找. 二分查找:Bin ...