290 likes | 543 Views
Hibernate 部分. JDBC 与 Hibernate 的区别. JDBC 操作的对象是关系型数据表中的数据 Hibernate 操作的对象是实体对象的状态 JDBC 关心的是如何调用和优化 SQL 语句 Hibernate 关心的是实体对象状态的转变,即对实体对象生命周期的管理 JDBC 使用 DataSource 和 Connection 作为 Java 程序操作数据库中数据的接口 Hibernate 使用 SessionFactory 和 Session 作为 Java 程序操作持久化上下文中实体对象的接口. Hibernate 中 Session 的概念.
E N D
JDBC与Hibernate的区别 • JDBC操作的对象是关系型数据表中的数据 • Hibernate操作的对象是实体对象的状态 • JDBC关心的是如何调用和优化SQL语句 • Hibernate关心的是实体对象状态的转变,即对实体对象生命周期的管理 • JDBC使用DataSource和Connection作为Java程序操作数据库中数据的接口 • Hibernate使用SessionFactory和Session作为Java程序操作持久化上下文中实体对象的接口
Hibernate中Session的概念 • Session是Java应用程序与Hibernate之间的主要运行时接口,是抽象了持久化服务概念的核心API类 • Session是Hibernate的持久化管理器,负责管理实体对象的状态 • Session的生命周期绑定在一个事务上 • Session对应持久化上下文,即Hibernate的一级缓存,记录一个事务中对实体对象做的所有修改和状态改变
实体对象的四种状态 • 瞬时状态 • 是利用new关键字实例化的对象 • 持久化状态 • 是一个保持与数据库同一性的实体对象 • 移除状态 • 是实体对象从计划被删除到真正从数据表中删除其所对应的数据行之前的状态 • 脱管状态 • 脱离持久化管理器(Session)管理的实体对象
瞬时状态 • 瞬时对象不与任何数据表中的数据关联 • 持久化上下文不会感知到瞬时对象中任何数据的修改 • Hibernate认为所有瞬时对象都是非事务的,不会为瞬时对象提供回滚功能
持久化状态 • 持久化对象始终与持久化上下文关联 • 持久化且被管理的对象与数据表中的相对应的数据行具有相同的ID • Hibernate在一级缓存中保存持久化对象 • Hibernate可以侦测到持久化对象的数据是否被程序修改
移除状态 • 当实体对象计划在事务结束时被删除,即成为移除状态的实体对象 • 直到事务完成后移除对象才会脱离持久化上下文的管理
脱管状态 • 所谓脱管状态的对象实质上是说该对象脱离了持久化管理器(Session)的管理 • 脱管状态对象中的数据不再保证与其对应的数据表中的数据同步
save和update的区别 • save的作用是把一个瞬时状态的对象转换为持久化状态的对象,表面上看也就是保存对象数据到数据库 • update是把一个脱管状态的对象转换为持久化状态的对象,也就是更新对象数据到数据库的操作
save、update和saveOrUpdate的区别 • save仅操作瞬时对象 • update仅操作脱管对象 • saveOrUpdate做以下事 • 如果对象已经在session中是持久化状态了,不做任何事 • 如果另一个与本session关联的对象拥有相同的持久化标识(id),抛出一个异常 • 如果对象没有持久化标识(id),对其调用save() • 如果对象的持久标识(id)表明其是一个新实例化的对象,对其调用save() • 如果对象是附带版本信息的(通过<version>或<timestamp>) 并且版本属性的值表明其是一个新实例化的对象,对其调用save() • 否则update() 这个对象
persist和save的区别 • save保证在执行后ID被立刻填入到持久化对象中去 • persist不保证ID被立刻填入到持久化对象中,ID的填入可能被推迟到flush执行时 • save无论是在事务内部还是外部,它会立即执行insert语句 • persist保证当它在一个事务外部被调用时并不触发Insert语句的执行
merge和update的区别 • 执行update后,所操作的实体对象变成持久化状态 • 执行merge后,所操作的对象A状态不变,Hibernate或者new了一个瞬时对象B,或者检索到一个持久化对象B,并把对象A上的所有数据拷贝到对象B上,执行完成后B是持久化状态的,而A还是原先的状态
flush和update的区别 • update操作的是在脱管状态的对象 • flush操作的是持久化态的对象 • 默认的,一个持久化状态的对象是不需要显式调用update的,只要更改了对象的值,等待hibernate flush就会把更新的值自动保存到数据库中。hibernate flush发生再几种情况下: • 调用某些查询的时候 • 事务提交的时候 • 手动调用flush的时候
lock和update的区别 • update是把一个已经更改过的脱管状态的对象变成持久化状态 • lock是把一个没有更改过的脱管状态的对象变成持久化状态 • 对应更改一个记录的内容,操作不同: • Update:更改脱管对象数据->调用update • Lock:把对象从脱管状态变成持久状态->更改脱管对象数据->等待flush • 新版本的Hibernate中lock方法的调用已经被buildLockRequest(LockMode).lock(object)方式替代了
get和load的区别 • load方式检索不到实体对象的话会则抛出org.hibernate.ObjectNotFoundException异常 • get方法检索不到实体对象的话会返回null • get方法首先查询一级缓存,没有的话查询二级缓存,最后查询数据库 • load方法首先查询一级缓存,没有就创建实体的代理对象,实际使用数据时才查询二级缓存和数据库
get和load的使用场景 • load方法认为该数据在数据库中一定存在,可以放心的使用代理对象来延迟加载数据,如果在使用过程中发现了问题,只能抛异常 • get方法是试探性的查询,所以一定要获取到真实的数据,否则返回null
list和iterate的区别(一) • list会直接查数据库,执行一条SQL语句 • iterate会先到数据库中把符合条件数据的id都取出来,当读取某个对象的数据时先到一级缓存中查找,如果找不到,以id为条件再发一条SQL到数据库,这样如果一级缓存中没有数据,则会执行n+1条SQL语句 • list不会从一级缓存读取数据,会重新查询后再刷新缓存 • iterate会先读取一级缓存,如果对象不存在,则会从数据库中查询数据
list和iterate的区别(二) • list中返回的每个对象都是实体对象本身 • iterate中返回的对象是实体对象的代理对象 • list方法会一次取出所有的结果集对象,并会依据查询的结果初始化所有的结果集对象。如果在结果集非常庞大的时候会占据非常多的内存,甚至会造成内存溢出 • iterate方法在执行时不会一次初始化所有的对象,而是根据对结果集的访问情况来初始化对象。在访问时可以控制缓存中对象的数量,以避免占用过多缓存而导致内存溢出情况的发生
Hibernate实体关联 • Hibernate实体关联,关键在于维护关联双方对象间的关系 • 在对关联双方进行数据写操作前,一定要把双方的关联关系建立完成
Hibernate实体关联分类 • 单向一对一关联 • 双向一对一关联 • 单向一对多关联 • 双向一对多关联 • 单向多对一关联 • 单向多对多关联 • 双向多对多关联
单向一对一关联 • 此图是夫妻单向一对一关系图,只有丈夫有权改变此关系 • 可以通过丈夫的wife属性访问妻子对象的数据,而不能通过妻子反向读取到丈夫的数据 • 只有丈夫一方才可以用set方法改变他们之间的关系
双向一对一关联 • 此图是夫妻双向一对一关系图,双方都有权改变此关系 • 可以通过丈夫的wife属性访问妻子对象的数据,也可以通过妻子的husband属性反向读取到丈夫的数据 Husband.java Wife.java
单向一对多关联 • 一方是主控方,持有一个存储多方对象的容器对象,通过此容器维护双方关系
双向一对多关联 • 一方持有一个存储多方对象的容器对象,多方各个对象持有一个一方对象的引用,双方关系可以通过对容器元素和对象引用的修改来维护双方关系 • 在使用双向一对多时,推荐把多的一方设置为主控方 • 在Java代码中始终要对双向关联的两端同时进行设置 General.java Country.java
单向多对一关联 • 多方是主控方,持有对一方对象的引用,通过此引用维护双方关系 • 单向一对多和单向多对一相对比,单向多对一关联更加常用;一个人被多个人记住是容易的,而多个人被一个人记住是很费力的
单向多对多关联 • 主控方对被控方持有维护关联的能力,而被控方不能维护双方的关系
双向多对多关联 • 主控被控双方彼此持有存储多个对方对象的容器,通过窗口可以维护双方关联关系 Role.java User.java
级联策略 • CascadeType.PERSIST:保存一个对象时,与之关联的对象也会被存储 • CascadeType.MERGE:当保存或更新一个对象时,与之关联的对象也会被保存或更新 • CascadeType.REMOVE:删除一个对象时,与之关联的对象也会被删除 • CascadeType.DETACH:使一个对象进入脱管状态后,与之关联的对象也会被变为脱管状态 • CascadeType.REFRESH:刷新一个对象时,与之关联的对象也会被刷新 • CascadeType.ALL:以上五类策略的并集