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 与 触发器协同工作
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
随机推荐
- Javascript的delete
Javascript中的激活对象(Activation object)和变量对象(Variable object):每个执行上下文在其内部都有一个Variable Object.与执行上下文类似,Va ...
- JSP 动作元素
JSP动作元素 1. 动作元素分类 用来动态的包含文件.网页跳转及使用JavaBean组件等. 语法:<jsp:XXX />或者<jsp:XXX></jsp:XXX&g ...
- maven遇到的问题
1.Missing artifact net.sf.json-lib:json-lib:jar:2.4:compile pom.xml原内容: <dependency> <group ...
- nginx+tomcat集群配置(4)--rewrite规则和多应用根目录设定思路
前言: nginx中有一块很重要的概念, 就是rewrite规则. 它会对URL进行修改, 然后进行内部的重定向. rewrite授予了nginx更多的自由, 使得后级服务的接入更加地方便. 本文将简 ...
- TCP状态变迁流程
主动建立TCP链接情况: 被动建立TCP链接情况 主动断开链接的情况 被动断开连接的情况 在TIME_WAIT阶段需要停留2倍的MSL,MSL即Maximum Segment Lifetime,表示任 ...
- [dijkstra+heap优化] 模板
var n,m,s,i,j,x,y,z,l,tot :longint; pre,last,other,len :..] of longint; heap,d,pl :Array[..] of long ...
- Lua与C++相互调用
{--1.环境--} 为了快速入手,使用了小巧快速的vc++6.0编译器 以及在官网下载了Lua安装包..官网地址{--http://10.21.210.18/seeyon/index.jsp--} ...
- C#委拖小例子
委托具有以下属性: 委托类似于 C++ 函数指针,但它们是类型安全的. 委托允许将方法作为参数进行传递. 委托可用于定义回调方法. 委托可以链接在一起:例如,可以对一个事件调用多个方法. 方法不必与委 ...
- mac10.9下eclipse的storm开发环境搭建
--------------------------------------- 博文作者:迦壹 博客地址:http://idoall.org/home.php?mod=space&uid=1& ...
- 使用swipecard实现卡片视图左右滑动监听以及点击监听
前言: 大家好,今天给大家介绍安卓一种特别实用有很酷炫的组件swipecard,当然这并不是安卓爸爸创造的,这是国内的一个我认为是大牛的一个人随便写着玩儿搞出来了,我看了他的代码介绍已经很清晰了,但 ...