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 与 触发器协同工作
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
随机推荐
- Python 基礎 - while流程判斷
接續上次的代碼,是不是只有執行一次才就結束,想要再繼續猜,就要在執行一次,是不是有點挺麻煩的? 所以這次我們就來再多做一點點功能進去,讓代碼可以多次循環地執行代碼,Go.... 首先,我們先來了解一下 ...
- java 读写JSON(一)
算是第一次正式接触Json,没有深入研究,先贴上java的代码,日后才说! package priv.chenhy.datehandle; import java.io.BufferedReader; ...
- Jena TDB 101 Java API without Assembler
Update on 2015/05/12 ongoing tutorials site on https://github.com/zhoujiagen/semanticWebTutorialUsin ...
- 【 D3.js 入门系列 --- 1 】 第一个程序HelloWorld
下面开始用D3.js处理第一个简单问题,先看下面的代码: <html> <head> <meta charset="utf-8"> <ti ...
- 该应用的登录功能版本较旧,无法使用QQ账号登录,请升级到最新版本,如果还无法解决,请联系开发者升级。(错误码:100044)
该原因应该是你的应用数据签名更改的原因 解决步骤已经写到我的公众号,二维码在下面. 欢迎观看我的CSDN学院课程,地址:http://edu.csdn.net/course/detail/2877 本 ...
- px和em区别-在font-size的 css 的使用
px像素(Pixel).相对长度单位.像素px是相对于显示器屏幕分辨率而言的. em是相对长度单位.相对于当前对象内文本的字体尺寸,多理解父级设定font-size的尺寸.如当前对行内文本的字体尺寸未 ...
- 10-Java 网络通信
(一) Java中的XML操作 1.XML数据格式简介: (1)XML,即可扩展标记语言(Extensible Markup Language),标准通用标记语言的子集,一种用于标记电子文件使其具有结 ...
- Docker SSH+NGHINX+MYSQL
1.添加创建镜像的配置文件 vim Dockerfile 输入以下内容: FROM jdeathe/centos-sshMAINTAINER baxk"xxx@hongh ...
- android数据存储之Sqlite(二)
SQLite学习笔记 前言:上一章我们介绍了sqlite的一些基本知识以及在dos命令下对sqlite进行的增删改查的操作,这一章我们将在android项目中实际来操作sqlite. 1. SQLit ...
- 利用硬链接和truncate降低drop table对线上环境的影响
众所周知drop table会严重的消耗服务器IO性能,如果被drop的table容量较大,甚至会影响到线上的正常. 首先,我们看一下为什么drop容量大的table会影响线上服务 直接执行drop ...