一、Session接口

       Session 是应用程序与数据库之间交互操作的一个单线程对象,是 Hibernate 运作的中心,所有持久化对象必须在 session 的管理下才可以进行持久化操作。此对象的生命周期很短。Session 对象有一个一级缓存,显式执行 flush 之前,所有的持久层操作的数据都缓存在 session 对象处。相当于 JDBC 中的 Connection

        **刷新缓存(flush):**session会根据缓存中对象向数据库发送对应的SQL。
        **加载:**session将数据库记录加载到session缓存中。

Hibernate教程之三:Session对象核心方法_hibernate

       Session 类的方法:

作用 方法
取得持久化对象的方法 get()、load()
持久化对象保存 save()、persist()、saveOrUpdate()
持久化对象更新 update()、saveOrUpdate()
持久化对象删除 delete()

 

                                          Hibernate中对象状态转换图

Hibernate教程之三:Session对象核心方法_对象_02

状态 解释
临时对象(Transient) 无OID、不在session缓存中、数据库中没有对应的记录
持久化对象(Persist) 有OID、在session缓存中、数据库有对应的记录、flush 缓存后数据库表与对象属性同步改变
删除对象(Removed) 有OID、不在session缓存、数据库中没有和它对应的数据
游离对象(Detached) 有OID、不在session缓存、数据库中可能有和它对应的数据

我们这么去解释:
       对象的状态是有一个参照物的,每一个对象参照的就是数据库中的每一行数据(通过OID唯一识别,也就是数据库表中的主键)。
       OID和主键的关系:OID针对的是一个实在的对象,主键是数据库概念

       下面我们具体讲解下这些方法的区别及用法

二、get()、load()方法的区别

场景 get方法 load方法
查询一个对象 立即加载 延迟加载
session被关闭 任然获得对象:Session was already closed异常 LazyInitializationException 异常
数据库中没有该记录;session没有被关闭 null 异常could not initialize proxy

延迟加载(本质是动态代理):查询只返回代理对象,只有用到了具体的属性才由代理对象去发送查询的sql

@Test
public void get() {
    User user=(User) session.get(User.class, 170618);
    session.close();
    System.out.println("user:"+user);
}

@Test
public void load() {
    User user=(User)session.load(User.class, 170618);
    session.close();
    System.out.println("user:"+user);
}

 

三、save()和persist()方法的区别

作用 save()方法 persist()方法
游离态转持久态
为对象分配ID
在Flush时会发送对应的sql
预设OID 无效,可插入 无效,抛异常,不可插入
方法后设置ID将抛出异常
@Test
public void save() {
    User user=new User();
    user.setId(23);//无效的
    user.setName("miemei");
    user.setTelPhone("857412369");
    System.out.println("user:"+user);

    session.save(user);
    System.out.println("user:"+user);
    //将报异常:user.setId(23);
}

@Test
public void persist() {
    User user=new User();
    user.setId(23);//无效的
    user.setName("ccccc");
    user.setTelPhone("0987654");
    System.out.println("user:"+user);

    session.persist(user);
}

 

四、refresh()和flush()、commit()方法区别

方法 功能
flush()方法 刷新全部对象、针对所有在session缓存中的持久态对象发送SQL(本质是执行了SQL),让持久化对象更新数据表行数据
refresh()方法 会强制发送 SELECT 语句, 以使 Session 缓存中对象的状态和数据表中对应的记录保持一致!让持久化对象与数据库表数据保持一致
commit()方法 这个方法的本质是提交已经执行的SQL操作、但是调用前会隐式调用flush()操作

*flush是使数据库表中的对象与session缓存的一致(发送UPDATE)
refresh是使session缓存中对象和数据库表中的一致(发送SELECT)

@Test
public void TestFlush() {
    //查询:发送一条语句
    User user1=(User) session.get(User.class,170618);
    //这时没发送sql:更改session内存中对象的属性值,但不更改数据库(也就是不发送sql)
    user1.setName("pangpang");
    //现在发送sql了,控制台可以看到了(但是没有提交事务)
    session.flush();

}


@Test
public void TestRefresh() {
    //session级缓存
    User user1=(User) session.get(User.class,170618);
    System.out.println("user1:"+user1); 
    //刷新指定的对象:user1
    session.refresh(user1);
    System.out.println("user1:"+user1); 
}

五、update()方法

功能 解释
更新持久化对象 不需要显示的调用 update 方法. 因为在调用 Transaction 的 commit() 方法时, 会先执行 session 的 flush 方法
更新游离态对象 需要显式的调用 session 的 update 方法. 可以把一个游离对象变为持久化对象
OID为空、数据库记录没有对应的主键ID 调用session的update将抛出异常
session缓存中有多个OID相同的对象 对其中一个对象执行session的update操作抛出异常

*update方法执行前:根据对象的OID去数据中查找对应的主键ID,当没有查到时,无法更新(抛出异常)。当查到的时候呀才发送更新语句。

@Test
public void testUpdate() {
    User user1=(User) session.get(User.class,170618);
    System.out.println("user1:"+user1);

    transaction.commit();
    session.close();

    session = sessionFactory.openSession();
    transaction = session.beginTransaction();

    //此时,user1对象已经相对于session对象为游离态,需要显示调用update
    user1.setName("胖胖");
    session.update(user1);
}

六、saveOrUpdate()方法

  • OID为空:执行save语句

  • OID不为空:执行update方法,当数据库表中没有对应的OID将报异常

  • 也可这么说:临时态对象执行save方法,游离态对象执行update方法
@Test
public void testSaveOrUpdate() {
    User user=new User();
    //user.setId(1);
    user.setName("weipang");
    user.setTelPhone("125874");
    session.saveOrUpdate(user);
}

七、delete()方法

  1. 先根据OID查找数据库
  2. 有匹配,执行删除
  3. 无匹配,抛异常
@Test
public void testDelete() {
    User user=(User) session.get(User.class,170618);
    session.delete(user);
    System.out.println("user:"+user);
}

 

八、eviet()方法和clear()、close()方法

方法 功能
eviet() 将session缓存中的指定对象从持久态变成游离态
clear() 将session缓存中所有的对象从持久态变成游离态
close() 关闭session,持久态变为游离态

 

@Test
public void testEvict() {
    User user=(User) session.get(User.class,170678);
    session.evict(user);
    user.setName("好胖呀");
}


@Test
public void testClear() {
    User user=(User) session.get(User.class,170678);
    User user1=(User) session.get(User.class,170639);
    session.clear();
    System.out.println("user:"+user);
    System.out.println("user1:"+user1);
    user.setName("好胖呀");
}

@Test
public void testClose() {
    User user=(User) session.get(User.class,170678);
    User user1=(User) session.get(User.class,170639);
    session.close();
    System.out.println("user:"+user);
    System.out.println("user1:"+user1);
    user.setName("好胖呀");
}

九、doWork()方法

这个本质就是获得JDBC原生的对象connection对象

@Test
public void testDoWork(){
    //本质是一个匿名内部类
    session.doWork(new Work() {
        @Override
        public void execute(Connection connection) throws SQLException {
            System.out.println(connection); 
            //调用存储过程. 
        }
    });
}