1.Session概述

  • Session接口是Hibernate向应用程序提供的操纵数据库最主要的接口,它提供了基本的保存,更新,删除和加载java对象的方法
  • Session具有一个缓存,位于缓存中的对象成为持久化对象,它和数据库中的相关记录对应,Session能够在某些时间点,按照缓存中对象的变化来执行相关的SQL语句,来同步更新数据库,这一过程被成为刷新缓存(flush)
  • 站在持久化的角度,Hibernate把对象分为4种状态:持久化状态,临时状态,游离状态,删除状态。Session的特定方法能使对象从一个状态转换到另一个状态

2.Session缓存

@Test
    public void testGet() {

        Session session = getSession();
        NewsEntity newsEntity = (NewsEntity) session.get(NewsEntity.class, 2);
        NewsEntity newsEntity1 = (NewsEntity) session.get(NewsEntity.class, 2);
        System.out.println(newsEntity);
        System.out.println(newsEntity1);
        session.close();
    }

该方法只会向数据库发送1条SQL语句。当进行第二次获取时,会从Session缓存中获取数据,而不是去向数据库查询

3.操作Session缓存

hibernate session 批量保存数据 hibernate的session_持久化

(1)flush缓存

  • Session按照缓存中对象的属性变化来同步更新数据库
  • 默认情况下Session在以下时间点刷新缓存:
  • 显示调用flush()方法
  • 调用Transaction的commit()方法(该方法先flush,再提交事务)
  • 当应用程序执行一些查询操作时,如果缓存中持久化对象的属性已经发生了变化,会flush缓存
  • 特殊情况:如果使用native生成器生成OID,那么当调用Session的save()方法保存对象,会立即执行插入操作

(2)设定刷新缓存的时间点

  • 若希望改变flush的默认时间点,可以通过Session的setFlushMode()方法显式设定flush的时间点
/*
  调用Session的查询方法时,清理缓存,注意:这条规则必须保证显式开启的事务中
  调用Session.commit()时,清理缓存
  调用Session.flush()时,清理缓存
*/
session.setFlushMode(FlushMode.AUTO);   //默认模式


/*  
  调用Session的查询方法时,不清理缓存
  调用Session.commit()时,不清理缓存
  调用Session.flush()时,清理缓存   
*/
session.setFlushMode(FlushMode.MANUAL);

/*
  调用Session的查询方法时,不清理缓存
  调用Session.commit()时,清理缓存
  调用Session.flush()时,清理缓存
*/
session.setFlushMode(FlushMode.COMMIT);


/*
调用Session的查询方法时,清理缓存,注意:这条规则必须保证显式开启的事务中
调用Session.commit()时,清理缓存
调用Session.flush()时,清理缓存
*/
session.setFlushMode(FlushMode.ALWAYS);

4.持久化对象的状态

Hibernate把对象分为4种状态:

持久化状态,临时状态,游离状态,删除状态

  • 临时对象(Transient)
  • 在使用代理主键的情况下,OID通常为null
  • 不处于Session的缓存中
  • 在数据库中没有对应的记录
  • 持久化对象(Persist)
  • OID不为null
  • 位于Session缓存中
  • 若在数据库中已经有和其对应的记录,持久化对象和数据库中的相关记录对应
  • Session在flush缓存时,会根据持久化对象的属性变化,来同步更新数据库
  • 在同一个Session实例的缓存中,数据库表中的每条记录只对应唯一的持久化对象
  • 删除对象(Removed)
  • 在数据库中没有和其OID对应的记录
  • 不再处于Session缓存中
  • 一般情况下,应用程序不该再使用被删除的对象
  • 游离对象(Detached)
  • OID不为null
  • 不再处于Session缓存中
  • 一般情况下,游离对象是由持久化对象转变过来的,因此在数据库中可能还存在与它对应的记录

5.对象的状态转换图

hibernate session 批量保存数据 hibernate的session_清理缓存_02

6.save()方法

  • Session的save()方法使一个临时对象转变为持久化对象
  • 当对象为持久化状态时,不允许程序随意修改它的ID
@Test
    public void testAdd() {

        Session session = getSession();
        //3. 开启事务
        Transaction transaction = session.beginTransaction();
        //4. 执行保存操作
        NewsEntity newsEntity = new NewsEntity();
        newsEntity.setTitle("java语句很强吗");
        newsEntity.setAuthor("hello123");
        newsEntity.setData(new Date());
        session.save(newsEntity);
        newsEntity.setId(5);
        //5. 提交事务
        transaction.commit();
        //6. 关闭 Session
        session.close();
    }
  • save()之后,又修改了NewsEntity,程序会抛出异常
  • persist()和save()的区别:
/**
     * persist(): 也会执行 INSERT 操作
     * 
     * 和 save() 的区别 : 
     * 在调用 persist 方法之前, 若对象已经有 id 了, 则不会执行 INSERT, 而抛出异常
     */
    @Test
    public void testPersist(){
        Session session = getSession();
        //3. 开启事务
        Transaction transaction = session.beginTransaction();
        //4. 执行保存操作
        NewsEntity newsEntity = new NewsEntity();
        newsEntity.setTitle("测试");
        newsEntity.setAuthor("java555");
        newsEntity.setData(new Date());
        newsEntity.setId(333);
        session.persist(newsEntity);
        //5. 提交事务
        transaction.commit();
        //6. 关闭 Session
        session.close();
    }
    
    /**
     * 1. save() 方法
     * 1). 使一个临时对象变为持久化对象
     * 2). 为对象分配 ID.
     * 3). 在 flush 缓存时会发送一条 INSERT 语句.
     * 4). 在 save 方法之前的 id 是无效的
     * 5). 持久化对象的 ID 是不能被修改的!
     */
    @Test
    public void testSave(){
        Session session = getSession();
        //3. 开启事务
        Transaction transaction = session.beginTransaction();
        //4. 执行保存操作
        NewsEntity newsEntity = new NewsEntity();
        newsEntity.setTitle("测试");
        newsEntity.setAuthor("java555");
        newsEntity.setData(new Date());
        newsEntity.setId(333);
        session.save(newsEntity);
        //5. 提交事务
        transaction.commit();
        //6. 关闭 Session
        session.close();
//      news.setId(101); 
    }

7.get()和load()方法

/**
     * get VS load:
     * 
     * 1. 执行 get 方法: 会立即加载对象. 
     *    执行 load 方法, 若不适用该对象, 则不会立即执行查询操作, 而返回一个代理对象
     *    
     *    get 是 立即检索, load 是延迟检索. 
     * 
     * 2. load 方法可能会抛出 LazyInitializationException 异常: 在需要初始化
     * 代理对象之前已经关闭了 Session
     * 
     * 3. 若数据表中没有对应的记录, Session 也没有被关闭.  
     *    get 返回 null
     *    load 若不使用该对象的任何属性, 没问题; 若需要初始化了, 抛出异常.  
     */

    @Test
    public void testLoad(){
        Session session = getSession();
        NewsEntity news = (NewsEntity) session.load(NewsEntity.class, 1);
        System.out.println(news.getClass().getName());

//      session.close();
//      System.out.println(news); 
    }

    @Test
    public void testGet1(){
        Session session = getSession();
        NewsEntity news = (NewsEntity) session.get(NewsEntity.class, 1);
//      session.close();
        System.out.println(news);
    }

8.update()方法

  • Session 的 update() 方法使一个游离对象转变为持久化对象, 并且计划执行一条 update 语句.
  • 若希望 Session 仅当修改了 News 对象的属性时, 才执行 update() 语句, 可以把映射文件中 <class> 元素的 select-before-update 设为 true. 该属性的默认值为 false
  • 当 update() 方法关联一个游离对象时, 如果在 Session 的缓存中已经存在相同 OID 的持久化对象, 会抛出异常
  • 当 update() 方法关联一个游离对象时, 如果在数据库中不存在相应的记录, 也会抛出异常

9.saveOrUpdate()方法


 


/**
     * 注意:
     * 1. 若 OID 不为 null, 但数据表中还没有和其对应的记录. 会抛出一个异常.
     * 2. 了解: OID 值等于 id 的 unsaved-value 属性值的对象, 也被认为是一个游离对象
     */
    @Test
    public void testSaveOrUpdate(){
        Session session = getSession();
        //3. 开启事务
        Transaction transaction = session.beginTransaction();
        NewsEntity news = new NewsEntity("FFF", "fff", new Date());
        news.setId(11);
        session.saveOrUpdate(news);
        //5. 提交事务
        transaction.commit();
        //6. 关闭 Session
        session.close();
    }

10.delete()方法

/**
     * delete: 执行删除操作. 只要 OID 和数据表中一条记录对应, 就会准备执行 delete 操作
     * 若 OID 在数据表中没有对应的记录, 则抛出异常
     *
     * 可以通过设置 hibernate 配置文件 hibernate.use_identifier_rollback 为 true,
     * 使删除对象后, 把其 OID 置为  null
     */
    @Test
    public void testDelete(){
        Session session = getSession();
        NewsEntity news = (NewsEntity) session.get(NewsEntity.class, 23);
        session.delete(news);

        System.out.println(news);
    }