欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Hibernate学习总结——SessionFactory对象和其他对象总结

程序员文章站 2024-03-21 20:33:46
...

SessionFactory对象

SessionFactroy接口负责初始化Hibernate。它充当数据存储源的代理,并负责创建Session对象。可以通过Configuration实例构建SessionFactory对象。

  1. SessionFactory是生成Session的工厂;当客户端发送一个请求线程时,SessionFactory生成一个Session 对象来处理客户请求。
  2. SessionFactory在应用初始化时被创建,是一个重量级的类,它在多个应用线程间进行被共享,通常情况下,整个应用只有唯一的一个会话工厂,然而,如果你使用Hibernate访问多个数据库,你需要对每一个数据库使用一个会话工厂
  3. SessionFactory是线程安全的,可以被多个线程调用。
Configuration cfg=new Configuration().configure(); 
SessionFactory sf=cfg.buildSessionFactory(); 

Session 对象

Session对象是Hibernate技术的核心,持久化对象的生命周期、事务的管理和持久化对象的查询、更新和删除都是通过Session对象来完成的。

  1. Session 是应用程序与数据库之间交互操作的一个单线程对象,是 Hibernate 运作的中心,所有持久化对象必须在 session 的管理下才可以进行持久化操作。此对象的生命周期很短
  2. Hibernate在操作数据库之前必须先取得Session对象,相当于JDBC在操作数据库之前必须先取得Connection对象一样
  3. Session对象通过SessionFactory对象的getCurrentSession()或者openSession()方法获取
    Configuration cfg= new Configuration().configure();
    SessionFactory sf= cfg.buildSessionFactory();
    Session session=sf.openSession();
  4. Session 类方法的用途可分为以下5类:

    – 取得持久化对象的方法: get(),load()
    – 持久化对象都得保存,更新和删除:save(),update(),saveOrUpdate(),delete()
    – 开启事务: beginTransaction().
    – 管理 Session 的方法:isOpen(),flush(),clear(),evict(),close()

Transaction对象

Transaction将应用代码从底层的事务实现中抽象出来——可能是一个JDBC事务或一个JTA事务,这有助于保持Hibernate应用在不同类型的执行环境或容器中的可移植性。

  1. 使用Hibernate进行操作时(增、删、改)必须显示的调用Transaction(默认autoCommit=false)
  2. Transaction的运行与Session接口相关,可调用Session的beginTransaction()方法生成一个Transanction实例。
    Transaction tx = session.beginTransaction();
  3. 常用方法:
    – commit():提交相关联的session实例
    – rollback():撤销事务操作
    – wasCommitted():检查事务是否提交

Hibernate持久化对象

  1. 持久化类的要求
    1. 必须提供一个无参数的构造函数可以不采用public访问控制符,但为了方便Hibernate在运行时生成代理,构造函数的访问控制符至少是包可见的(即大于或等于默认的访问控制符)
    2. 提供一个标识属性:通常映射数据库表的主键字段;可以是任何名字、任何类型(基本类型、包装类、String或Date);如果使用联合主键,甚至可以用一个用户自定义的类,该类包括这些类型的属性
    3. 为持久化类的每个成员变量提供setter和getter方法;注意:变量名首字符小写
    4. 使用非final的类,在运行时生成代理是Hibernate的一个重要功能。如果持久化类没有实现任何接口,使用Javassist生成代理,该代理对象是持久化类的子类的对象;如果使用了final类,就无法生成Javassist代理,因此需要让Hibernate持久化类实现一个所有方法都声明为public的接口,此时将使用JDK代理,同时避免在非final类中声明public final方法。如果必须要有一个final方法,必须设置lazy=“false”明确的禁用代理

相关名词

  1. OID(Object Identifier, OID):来建立内存中的对象和数据库表中记录的对应关系,对象的OID和数据库表的主键(通常为代理主键,即不具备业务含义的字段,该字段一般取名为ID)对应。它是hibernate用于区分两个对象是否是同一个对象的标识。为了保证持久化对象的OID的唯一性和不可变性,通常由Hibernate或底层数据库来给OID赋值。因此,可以把OID的setId()方法设为private类型,以禁止Java应用程序随便修改OID;而把getId()方法设为public类型,这使得Java应用程序可以读取持久化对象的OID
  2. 自然主键:把具有业务含义的字段作为主键,称之为自然主键。
  3. 代理主键:把不具备业务含义的字段作为主键,称之为代理主键。该字段一般取名为“ID”,通常为整数类型,因为整数类型比字符串类型要节省更多的数据库空间。
  4. hibernate中的一级缓存:是指Session缓存,Session缓存是一块内存空间,用来存放相互管理的java对象,在使用Hibernate查询对象的时候,首先会使用对象属性的OID值在Hibernate的一级缓存中进行查找,如果找到匹配OID值的对象,就直接将该对象从一级缓存中取出使用,不会再查询数据库;如果没有找到相同OID值的对象,则会去数据库中查找相应数据。当从数据库中查询到所需数据时,该数据信息也会放置到一级缓存中。Hibernate的一级缓存的作用就是减少对数据库的访问次数。
    在运行时,Hibernate根据OID来维持Java对象和数据库中的对应关系。如下所示:
    Transaction tx = session.beginTransaction();
    User user1 = (User)session.load(User.class,new Long(1));
    User user2 = (User)session.load(User.class,new Long(1));
    User user3 = (User)session.load(User.class,new Long(3));
    应用程序在执行上述代码时,第一次OID为1的对象,从数据库中查找ID为1的记录,然后创建想要的User实例,并把它保存到session的缓存中,最后将该实例的引用赋值给变量user1,第二次加载OID为1的对象时,直接把session缓存中的OID为1的实例的引用赋值给user2,因此user1=user2的结果为true
  5. 快照机制:Hibernate 向一级缓存放入数据时,同时复制一份数据放入到Hibernate快照中,当使用commit()方法提交事务时,同时会清理Session的一级缓存,这时会使用OID判断一级缓存中的对象和快照中的对象是否一致,如果两个对象中的属性发生变化,则执行update语句,将缓存的内容同步到数据库,并更新快照;如果一致,则不执行update语句。Hibernate快照的作用就是确保一级缓存中的数据和数据库中的数据一致。

持久化对象的状态

临时态(*态)

  1. 由new命令开辟内存空间时刚生成的Java对象就处于临时态。
    例如:UserInfoPO ui=new UserInfoPO();
  2. 临时对象在内存中是孤立存在,它是携带信息的载体,不和数据库的数据有任何关联关系,在Hibernate中,可通过session的save()或saveOrUpdate()方法将临时对象与数据库相关联,并将数据对应的插入数据库中,此时该临时对象转变成持久化对象。
  3. 没有OID,没有和Session建立关系(没有存入Session的一级缓存),数据表中行数据与对象没有关系

持久态

  1. 处于该状态的对象在数据库中具有对应的记录,并拥有一个持久化标识。如果是用Hibernate的delete()方法,对应的持久对象就变成临时对象,因数据库中的对应数据已被删除,该对象不再与数据库的记录关联。
  2. 当一个session执行close()或clear()、evict()之后,持久对象变成脱管对象,此时持久对象会变成脱管对象,此时该对象虽然具有数据库识别值,但它已不在Hibernate持久层的管理之下。
  3. 持久对象具有如下特点:
    – 和session实例关联。
    – 在数据库中有与之关联的记录。
    有OID,和Session建立关系(存入Session的一级缓存),数据表中行数据与对象建立关系

脱管态(游离态)

  1. 当与某持久对象关联的session被关闭后,该持久对象转变为脱管对象。当脱管对象被重新关联到session上时,并再次转变成持久对象。
  2. 脱管对象拥有数据库的识别值,可通过update()、saveOrUpdate()等方法,转变成持久对象。
  3. 脱管对象具有如下特点:
    – 本质上与临时对象相同,在没有任何变量引用它时,JVM会在适当的时候将它回收。
    – 比临时对象多了一个数据库记录标识值。
    – 有OID,和Session没有关系(从Session的一级缓存中移除),数据表中行数据与对象没有关系

Session的基本操作

1. save()方法

– Session的save()方法使一个临时对象转变为持久化对象
Session的save() 方法完成以下操作:

  1. 把News对象加入到 Session 缓存中, 使它进入持久化状态
  2. 选用映射文件指定的标识符生成器, 为持久化对象分配唯一的 OID. 在使用代理主键的情况下, setId()方法为对象设置OID是无效的.执行save()方法之前,修改对象id的操作是无效的。
  3. 计划执行一条insert语句:在flush缓存的时候
    Hibernate通过持久化对象的OID来维持它和数据库相关记录的对应关系。当News对象处于持久化状态时,不允许程序随意修改它的ID
2. persist()方法 【Save_Persis】

save()和 persist()方法还有一个区别:

  1. 返回类型不同,save返回Serializable对象,而persist返回void
  2. ID赋值时机不同,二者同样用于将transient实例持久化,但persist不保证ID值立即赋给持久化实例,可能会在flush的时候给ID赋值。
  3. transaction外的行为不同,save方法会导致insert语句的立即执行;persist如果在transaction之外调用,不会导致insert语句的立即执行,而是在flush时执行insert语句。persist如果在transaction之内调用,会导致insert语句的立即执行。
  4. 使用场景,由于上述第三点区别,persist方法适用于被扩展的Session上下文的长期运行的会话中;而save则不适用。

如果标识属性时自动生成,那么Hibernate将会在执行save方法时自动生成标识属性,并将该标识属性值分配给对象;如果标识属性是assigned(指派)属性或复合主键那么标识属性值应当在调用save之前手动赋给对象

3. get()和load()方法 【Load_Get】

都可以根据给定的 OID 从数据库中加载一个持久化对象
区别:
使用get()来根据ID进行单条查询,当get()方法被调用的时候就会立即发出SQL语句;当调用load()方法的时候会返回一个目标对象的代理对象。在使用对象之前提前关闭了session会发生懒加载异常。get方法不存在这个问题。
当数据库中不存在与 OID 对应的记录时,Session没有关闭且同时需要使用对象时, load() 方法抛出 ObjectNotFoundException 异常, 而 get() 方法返回 null

Hibernate学习总结——SessionFactory对象和其他对象总结
Hibernate学习总结——SessionFactory对象和其他对象总结
Hibernate学习总结——SessionFactory对象和其他对象总结

懒加载异常
Hibernate学习总结——SessionFactory对象和其他对象总结
在hibernate设置延迟加载后,hibernate返回给我们的对象(要延迟加载的对象)是一个代理对象并不是真实的对象,该对象没有真实对象的数据,只有真正需要用到对象数据(调用getter等方法时)时,才会触发hibernate去数据库查对应数据,而且查回来的数据不会存储在代理对象中,所以这些数据是无法在调试窗口查看到的。

4. update() 方法 【update】
  1. Session 的 update() 方法使一个游离对象转变为持久化对象, 并且计划执行一条 update 语句.
  2. 若希望 Session 仅当修改了 News 对象的属性时, 才执行 update() 语句, 可以把映射文件中 元素的 select-before-update 设为 true. 该属性的默认值为 false
  3. 抛出异常的两种情况:
    a) 当 update() 方法关联一个游离对象时, 如果在 Session 的缓存中已经存在相同 OID 的持久化对象, 会抛出异常
    b) 当 update() 方法关联一个游离对象时, 如果在数据库中不存在相应的记录, 也会抛出异常.
5. saveOrUpdate方法
  1. 有save()和update()方法的功能,对于传入的对象,首先会执行一遍查询语句判断该对象在数据库中是否存在,然后调用相应的方法。
  2. 如果传入该方法的是一个脱管对象,那么这个方法就会执行update操作,如果传入该方法的是一个临时对象,那么这个方法就会执行insert操作。
6. merge方法 【merge】
  1. 新new一个对象,如果该对象设置了ID,则这个对象就当作游离态处理:
    ⌂ 当ID在数据库中不能找到时,用update的话肯定会报异常,然而用merge的话,就会insert
    ⌂ 当ID在数据库中能找到的时候,update与merge的执行效果都是更新数据,发出update语句;
  2. 如果没有设置ID的话,则这个对象就当作瞬态处理:用update的话,由于没有ID,所以会报异常,merge此时则会保存数据,根据ID生产策略生成一条数据;
    Hibernate学习总结——SessionFactory对象和其他对象总结
    Hibernate学习总结——SessionFactory对象和其他对象总结
    merge和saveOrUpdate方法区别在于:merge方法是把我们提供的对象转变为托管状态的对象;而saveOrUpdate则是把我们提供的对象变成一个持久化对象;说的通俗一点就是:saveOrUpdate后的对象会纳入session的管理,对象的状态会跟数据库同步,再次查询该对象会直接从session中取,merge后的对 象不会纳入session的管理,再次查询该对象还是会从数据库中取。
7. delete() 方法 【Delete】
  1. Session 的 delete() 方法既可以删除一个游离对象, 也可以删除一个持久化对象
  2. Session 的 delete() 方法处理过程
    a 计划执行一条 delete 语句
    b 把对象从 Session 缓存中删除, 该对象进入删除状态.
  3. Hibernate 的 cfg.xml 配置文件中有一个 hibernate.use_identifier_rollback 属性, 其默认值为 false, 若把它设为 true, 将改变 delete() 方法的运行行为: delete() 方法会把持久化对象或游离对象的 OID 设置为 null, 使它们变为临时对象
8. evict () 方法

从 session 缓存中把指定的持久化对象移除,对象从持久化状态变为脱管状态。
Session中的clear是完成将session中的缓存清除。而evcit则是清除缓存中某个持久化的对象。即只把某个持久化的对象从缓存中移除。