站在持久化的角度, 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对象的状态的更多相关文章

  1. Hibernate对象的状态和映射

    一. Hibernate对象的状态 实体对象的三种状态: 1) 暂态(瞬时态)(Transient)---实体在内存中的自由存在,它与数据库的记录无关. po在DB中无记录(无副本),po和sessi ...

  2. Hibernate(3)——实例总结Hibernate对象的状态和ThreadLoacl封闭的session

    俗话说,自己写的代码,6个月后也是别人的代码……复习!复习!复习!涉及的知识点总结如下: Hibernate的内部执行过程(CRUD) 对象的状态及其转换图和例子 使用JUnit测试 使用getCur ...

  3. Hibernate对象的状态分类

    对象的状态: 临时状态Transient: 与数据库没有对应,跟Session没有关联 一般是新new出的对象 持久化状态Persistent: 对象在Session的管理之中,最终会有对应的数据库记 ...

  4. Hibernate对象的状态转换

    Hibernate中的实体对象可以分为三种状态:Transient(临时).Persistent(持久).Detached(游离) Transient 用new创建出对象,这些对象还没有与数据库发生任 ...

  5. hibernate对象的状态以及生命周期

    瞬时状态:session中没有,数据库中没有 持久状态:session中有,数据库中有 游离状态:session中没有,数据库中有 get和load都是用来提取数据的 get和load的区别: get ...

  6. 菜鸟学SSH(八)——Hibernate对象的三种状态

    前面写了几篇关于SSH的博客,但不是Struts就是Spring,Hibernate还从来没写过呢.说好是SSH的,怎么可以光写那两个,而不写Hibernate呢对吧.今天就先说说Hibernate对 ...

  7. hibernate对象的三种状态

    对于hibernate,我想不在这里讲解了,我们就直接进入主题 在这里我将要说的是"hibernate对象的三种状态",对象是我们十分熟悉的,对吧!而对于对象它有三种状态 分别是瞬 ...

  8. hibernate对象三种状态

    在Hibernate中,对象有三种状态:临 时状态(Transient).持久状态(Persistent)和游离状态(Detached). 处于持久态的对象也称为 PO(PersistenceObje ...

  9. [原创]java WEB学习笔记79:Hibernate学习之路--- 四种对象的状态,session核心方法:save()方法,persist()方法,get() 和 load() 方法,update()方法,saveOrUpdate() 方法,merge() 方法,delete() 方法,evict(),hibernate 调用存储过程,hibernate 与 触发器协同工作

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

随机推荐

  1. java中时间类型的问题

    时间类型:System.currentTimeMillis() 获得的是自1970-1-01 00:00:00.000 到当前时刻的时间距离,类型为longimport java.sql.Date d ...

  2. Socket编程基础——无连接UDP

    与面向连接的网络连接相比,无连接的网络通信不需要在服务器与客户端之间建立连接.面向非连接的Socket通信是基于UDP的,服务器端不需要调用listen()和accept()函数来等待客户端的连接:客 ...

  3. python数据结构与算法——图的最短路径(Bellman-Ford算法)解决负权边

    # Bellman-Ford核心算法 # 对于一个包含n个顶点,m条边的图, 计算源点到任意点的最短距离 # 循环n-1轮,每轮对m条边进行一次松弛操作 # 定理: # 在一个含有n个顶点的图中,任意 ...

  4. mm/vmalloc.c

    /* *  linux/mm/vmalloc.c * *  Copyright (C) 1993  Linus Torvalds */ #include <asm/system.h>#in ...

  5. Yahoo Pure 中文参考手册

    Pure 是来自雅虎的 CSS 框架,使用 Normalize.CSS 无需任何 JavaScript 代码.框架基于响应式设计,提供多种样式的组件,包括表格.表单.按钮.表.导航等.标识使用非常简单 ...

  6. Notepad++配置Python开发环境

    1. 安装Python 1 下载 我选择了32位的2.7版本.https://www.python.org/ftp/python/2.7.8/python-2.7.8.msi 2. 安装 安装的时候可 ...

  7. 综合使用union和limit区分结果并限制返回结果集的条数

    limit , 这里的limit限制了返回的union(合并)后的结果集,

  8. 为什么引用不了App_Code里的类(报“未能找到类型或命名空间名称”错误)

    在Web应用程序中不能通过右键项目-〉”添加“-〉”添加ASP.NET文件夹“方式添加 .因为Web应用程序中App_Code就不存在 . 不过可以通过手动的方式创建,添加一个文件夹命名为App_Co ...

  9. Spring MVC入门实战(一)

    本文主要把一个菜鸟从“只是听说过Spring MVC”到“可以手动创建并运行一个Spring MVC工程”的过程记录下来,供以后复习. 0. 开发环境准备 计算机平台:Windows 7 X64. 需 ...

  10. Openstack Neutron L2 Population

    Why do we need it, whatever it is? VM unicast, multicast and broadcast traffic flow is detailed in m ...