Hibernate之Session方法

一、Session中方法

1、开启一个事务:
Transaction beginTransaction()
2、获取一个事务:
Transaction getTransaction()
3、保存一个对象:
Serializable save(Object o)
4、修改一个对象:
void update(Object o)
5、删除一个对象:
void delete(Object o)
6、根据主键查询指定类型的对象:
Object get(Class type,Serializable id)
7、根据hql创建一个查询对象
Query createQuery(String hql)
8、关闭Session:
void close()
9、清除一级缓存所有对象:
void clear()
10、清除一级缓存中制定的对象:
void evict(Object o)

1、事务相关的方法

  • Transactionsession.beginTransaction():标记打开当前session绑定的事务对象
  • Transactionsession.getTransaction():得到和当前session绑定的事务对象。

2、一级缓存相关

  • session.clear():清除一级缓存中所有的对象。
  • boolean contains(Objectentity):判断一级缓存中是否有给定的对象。
  • session.evict(Objectentity):从一级缓存中清除指定的对象。
  • session.flush():把一级缓存中的脏数据同步到数据库中。
  • session.refresh(Objectentity):强制重新查询对象,相当于把数据库中的数据同步到一级缓存中。

3、持久化操作相关:

  • 1、 session.delete(Object entity):从数据库中删除一个对象
  • 2、 session.update(Objectentity):更新一个对象
  • 3、session.get(ClassentityType,Serializableid):根据主键查询一个对象
  • 4、session.load(ClassentityType,Serializableid):根据主键加载一个对象
    • 4.1、load方法是一个延时加载的方法,把对象的获取(SQL)延迟到了真正使用这个对象的时候才发送。
    • 4.2、真正使用?当使用一个非主键属性的时候
    • 4.3、load实现原理?使用动态代理,为load的domain动态创建了一个子类,在这个子类中,复写所有非主键调用方法,在这些方法中,去发送
  • 5、session.save(Objectentity):保存一个对象
  • 6、session.persist(Objectentity):保存一个对象
    • 6.1、同步JPA的接口方法
    • 6.2、和save的区别:在没有事务环境下,save方法会发送INSERT SQL,而persist不会
    • 6.3、session.saveOrUpdate():如果对象没有保存到数据库,则保存,如果已经保存过,则更新。在没有事务环境下,saveOrUpdate方法会发送INSERT SQL,merge不会
    • 6.4、session.merge():等同于saveOrUpdate()
  • 7、session.close():关闭session之后,就不能在使用这个session完成持久化相关的操作
  • 8、session.doWork(Work work):Hibernate提供给程序员直接使用JDBC的一个途径
  • 9、session.doReturningWork(ReturningWork):Hibernate提供给程序员直接使用JDBC的一种途径
  • 10、Serializablesession.getIdentifier(Objectentity):得到一个对象的主键值

4、持久化方法

在Hibernate中persist和方法save方法都表示保存一个对象

  • save方法是:Hibernate自身提供的方法
  • persist方法是:JPA规范中的方法,Hibernate实现了JPA规范,那么就得提供persist方法
    但是persist方法必须运行在事务空间内
  • session.save():没有事务环境,也会发送INSERT INTO语句,但是不会保存成功
    public void save(User user) {
        Session session = HibernateUtil.getHibernateSession();
        //5、设置事务的开启状态
//        session.beginTransaction();
        //6、具体操作
        session.save(user);
        //7、提交事务
//        session.getTransaction().commit();
    }
Hibernate: 
    insert 
    into
        t_user
        (name, date) 
    values
        (?, ?)
  • session.persist():没有事务环境,不会发送INSERT INTO语句(推荐),不会保存成功
    public void save(User user) {
        Session session = HibernateUtil.getHibernateSession();
        //5、设置事务的开启状态
//        session.beginTransaction();
        //6、具体操作
//        session.save(user);
        session.persist(user);
        //7、提交事务
//        session.getTransaction().commit();
    }

5、保存或更新方法:

session.saveOrUpdate(Object en):如果对象之前没有存储到数据库,则保存,如果已经保存过,则更新。

  • 如果对象存在OID,则update

  • 如果对象不存在OID,则save

  • merge方法是JPA提供的方法,功能和saveOrUpdate等价

  • merge方法相当于saveOrUpdate方法,必须运行在事务空间内

  • 5.1、saveOrUpdate没有事务

    public void saveOrUpdate(User user) {
        Session session = HibernateUtil.getHibernateSession();
        session.saveOrUpdate(user);
    }
Hibernate: 
    insert 
    into
        t_user
        (name, date) 
    values
        (?, ?)
  • 5.2、saveOrUpdate有事务
    public void saveOrUpdate(User user) {
        Session session = HibernateUtil.getHibernateSession();
        session.beginTransaction();
        session.saveOrUpdate(user);
        session.getTransaction().commit();
    }
  • 5.2.1、user对象没有OID
Hibernate: 
    insert 
    into
        t_user
        (name, date) 
    values
        (?, ?)
  • 5.2.2、user对象有OID
Hibernate: 
    update
        t_user 
    set
        name=?,
        date=? 
    where
        id=?
  • 小结:
    saveOrUpdate

    • 1、没有事务时:(操作不成功)

      • 1.1:没有OID时,发送INSERT INTO语句
      • 1.2:存在OID时,没有发送UPDATE语句
    • 2、存在事务环境:(操作成功)

      • 2.1:没有OID时,发送INSERT INTO语句
      • 2.2:存在OID时,发送UPDATE语句
  • 5.3、merge没有事务
    没有OID:没有发送INSERT INTO语句

    public void saveOrUpdate(User user) {
        Session session = HibernateUtil.getHibernateSession();
        session.merge(user);
    }

存在OID:发送SELECT语句,没有发送UPDATE语句

Hibernate: 
    select
        user0_.id as id1_0_0_,
        user0_.name as name2_0_0_,
        user0_.date as date3_0_0_ 
    from
        t_user user0_ 
    where
        user0_.id=?
  • 5.4、merge存在事务环境
    没有OID:发送INSERT INTO语句
    public void saveOrUpdate(User user) {
        Session session = HibernateUtil.getHibernateSession();
        session.beginTransaction();
        session.merge(user);
        session.getTransaction().commit();
    }
Hibernate: 
    insert 
    into
        t_user
        (name, date) 
    values
        (?, ?)

存在OID:发送SELECT语句,发送UPDATE语句

Hibernate: 
    select
        user0_.id as id1_0_0_,
        user0_.name as name2_0_0_,
        user0_.date as date3_0_0_ 
    from
        t_user user0_ 
    where
        user0_.id=?
Hibernate: 
    update
        t_user 
    set
        name=?,
        date=? 
    where
        id=?

6、get和load方法

get方法返回的总是持久化状态的对象;get方法立刻发送一条SELECT语句,结果可以用if-null来判断对象是否为空
load方法并不会立刻发送一条SELECT语句去查询对象,而要到了真正在使用一个非主键属性的时候,才会去发送SELECT语句,我们把这种方式叫做延迟加载(lazy-load)/ 懒加载

  • 6.1:如果对象没有被加载过,则会发送一条SELECT语句,去加载对象,再返回属性值

  • 6.2:load方法返回的对象永远不可能为空,所以不能使用if-null来判断。为什么load方法返回的对象永远不为null,即使OID不存在,在load方法执行的方法,根据不会发生SELECT的SQL语句,也就不知道查询结果是否为空,就索性返回一个不为空的对象。如果当前查询的OID在数据库存在,就把数据封装到该对象中,如果当前查询的OID不在数据库中,此时就立刻报错

  • 6.3:load原理

  • 6.3.1:Hibernate框架的中的javassist组件创建了代理类及对象

  • 6.3.2:该对象提供了非主键属性的getter方法和toString方法,感觉上代理对象和真实对象是一样的

  • 6.3.3:该对象存在是否加载完毕的状态,访问属性是先判断对象是否加载完毕,如是直接返回该属性,否则发送SQL查询该对象

二、持久化对象生命周期

1、状态

问题1:主键生成策略不同,save操作时发生INSERT语句的时机不同

  • native:执行save方法的时候就立刻发送INSERT语句
  • increment:执行save方法的时候没有发送INSERT语句,而是在提交事务时发送
    问题2:删除对象的时候,没有立刻发送DELETE语句,而是在提交事务的时候发送的
    问题3:为什么在事务环境下,通过get方法得到的对象,只要修改了属性值,才会发生UPDATE语句
    总结:执行session中的方法和SQL的发送没有关系,session中的方法仅仅和对象的状态有关系

2、对象的四种状态

1、临时状态/瞬时态(transient):刚刚用new语句创建,没有被持久化(save),不处于session中。特点:没有OID,不在session缓存中
2、持久化状态(persistent):已经被持久化,加入到session的缓存中。特点:有oid,在session的一级缓存中
3、脱管状态/游离状态(detached):已经被持久化,但不处于session中。特点:有oid,不在session中
4、删除状态(removed):对象有关联的ID,并且在session管理下,但是已经计划被删除。特点:有oid,在session缓存中,最终被删除

状态一:临时状态

  • new语句刚创建了一个对象
  • 删除状态的对象,在事务提交之后,对象处于临时状态

状态二:删除状态

  • 持久化状态和游离状态对象执行delete()

状态三:持久化状态

  • save方法把临时状态转换为持久化状态
  • save方法把游离对象变成另一个持久化状态.

状态四:游离状态

  • session.close()方法把所有的持久化对象变成游离对象.
  • session.clear()方法把所有持久化对象变成游离对象.
  • session.evivt(Object)方法把制定的持久化对象变成游离对象.
  • 使用new创建对象,并设置OID(数据库存在该ID);


    session状态.png

三、对象状态总结

问题1: 主键生成策略不同,save操作时发送INSERT语句的时机不同.

native:执行save方法的时候就立刻发送INSERT语句.
increment:执行save方法的时候没有发送INSERT语句,而是在提交事务时发送.

临时状态--->持久化状态:从没有OID变的有OID了,过程中会想尽方式获取一个OID值并设置在对象上.
native方式,是数据库自增的方式,只有执行INSERT语句,才能获取自动生成的主键(OID).

increment方式:是Hibernate的自增方式,会先发送SELECT  MAX(主键) FROM 表,递增1之后,
就是这一次保存的OID值.此时不需要执行INSERT语句,就可以获取OID,所以并没有立刻发送INSERT语句.
INSERT语句是提交事务的时候,才发送的.

问题2: 删除对象的时候,没有立刻发生DELETE语句,而是在提交事务的时候发送的.

因为delete方法仅仅表示把游离状态对象/持久化状态对象变成删除状态,不负责发送SQL.

问题3: 为什么在事务环境下,通过get方法得到的对象,只要修改了非IOD属性值,会发生UPDATE语句.

引入一级缓存的快照区.
  当把通过get方法查询出一个对象的时候,该对象同时存储在一级缓存中,也同时存储在session的快照区.
  在通过修改了对象的非IOD属性.(p.setName(“XXX”)),此时就把一级缓存中数据改变了.
  默认情况下,在事物提交的时候,就会去检查一级缓存中数据和快照区数据是否一致,如果不一致,
就发送UPDATE语句把一级缓存中的数据同步到数据库.

四、发送SQL的时机

默认情况下,在事务提交时,会自动去数据库同步这一次对象变化对应的SQL,事务提交的时候,发送什么SQL?

  • 临时状态-->持久化状态:发送INSERT.
  • 持久化状态/游离状态--->删除状态:发送DELETE.
  • 游离状态-->持久化状态:发送SQL
  • 脏的持久化对象同步到数据库.(session快照)
  • session.flush()方法可以手动同步数据库.
    总结:由session的持久化方法修改对象的状态,在同步session数据的时候(默认是提交事务,也可以是flush),session再同步脏数据到数据库,完成内存对象和数据库的同步。
    session中的方法只负责改变对象的状态,事务负责同步数据

你可能感兴趣的:(Hibernate之Session方法)