A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 我是色色 于 2017-12-20 10:48 编辑

Hibernate事务管理事务介绍
问题:什么是事务?
        事务就是逻辑上的一组操作,组成这组操作的各个单元要么全部成功,要么全都失败。
问题:事务四个特性?
        原子性:不可分割
        一致性:事务在执行前后,要保证数据的一致。
        隔离性:一个事务在执行的过程中,不应该受到其它事务的干扰。
        持久性:事务一旦结束,数据持久化到数据库。
问题:不考虑事务的隔离性,会产生什么问题?
        脏读:一个事务读取到另一个事务的未提交数据
不可重复读:一个事务读取到另一个事务提交的数据(主要是指update),会导致两次读取的结果不一致。
虚读(幻读): 一个事务读取到另一个事务提交的数据(主要是指insert),会导致两次读取结果不一致.
问题:对于上述问题如何解决?
        我们可以通过设置隔离级别来解决.
        READ_UNCOMMITED 读取未提交,它引发所有的隔离问题
        READ_COMMITTED  读已提交,阻止脏读,可能发生不可重复读与虚读.
        REPEATABLE_READ 重复读  阻止脏读,不可重复读 可能发生虚读
SERIALIZABLE 串行化 解决所有问题 不允许两个事务,同时操作一个目标数据。(效率低下)
ORACLE  默认的是事务隔离级别  READ_COMMITTED
MYSQL 默认的事务隔离级别  REPEATABLE_READ
Hibernate中设置事务隔离级别
hibernate.connection.isolation
它可取的值有 1 2 4 8
1代表的事务隔离级别为READ UNCOMMITTED
2代表的事务隔离级别为READ COMMITTED
4.代表的事务隔离级别为 REPEATABLE READ
8代表的事务隔离级别为 SERIALIZABLE
在hibernate.cfg.xml文件中配置
Hibernate中session管理
Hibernate提供了三种管理session的方式:
1. Session对象的生命周期与本地线程绑定(ThreadLocal)
2. Session对象的生命周期与JTA事务绑定(分布式事务管理)
3. Hibernate委托程序来管理Session的生命周期
我们之前所使用的是第三种 ,通过程序获取一个Session对象,使用它,最后session.close();
在实际开发中我们一般使用的是前两种:
        主要介绍关于本地线程绑定Session。
        步骤:
1. 需要在hibernate.cfg.xml文件配置
2. 在获取session时不要在使用openSession而是使用getCurrentSession()方法。
关于getCurrentSession使用时的注意事项:
上述代码执行后,会产生问题
原因:使用getCurrentSession获取的与线程绑定的session对象,在事务关闭时,session对象也会close,简单说,就不需要我们在手动close;
Hibernate优化方案HQL优化1.使用参数绑定
        1.使用绑定参数的原因是让数据库一次解析SQL,对后续的重复请求可以使用用生成好的执行计划,这样做节省CPU时间和内存。
        2.避免SQL注入
2.尽量少使用NOT
        如果where子句中包含not关键字,那么执行时该字段的索引失效。
3.尽量使用where来替换having
Having在检索出所有记录后才对结果集进行过滤,这个处理需要一定的开销,而where子句限制记录的数目,能减少这方面的开销
4.减少对表的查询
        在含有子查询的HQL中,尽量减少对表的查询,降低开销
5.使用表的别名
当在HQL语句中连接多个表时,使用别名,提高程序阅读性,并把别名前缀与每个列上,这样一来,可以减少解析时间并减少列歧义引起的语法错误。
6.实体的更新与删除
        在hibernate3以后支持hql的update与delete操作
一级缓存优化
一级缓存也叫做session缓存,在一个hibernate session有效,这级缓存的可干预性不强,大多于hibernate自动管理,但它提供清除缓存的方法,这在大批量增加(更新)操作是有效果的,例如,同时增加十万条记录,按常规进行,很可能会出现异常,这时可能需要手动清除一级缓存,session.evict以及session.clear.
检索策略(抓取策略)延迟加载
延迟加载 是hibernate为提高程序执行的效率而提供的一种机制,即只有真正使用该对象的数据时才会创建。
load方法采用的策略延迟加载.
get方法采用的策略立即加载。
检索策略分为两种:
1. 类级别检索
2. 关联级别检索
类级别检索
类级别检索是通过session直接检索某一类对应的数据,例如
Customer c=session.load(Customer.class,1)
Session.createQuery(“from Order”)
类级别检索策略分为立即检索与延迟检索,默认是延迟检索,类级别的检索策略可以通过<class>元素的lazy属性来设置 ,默认值是true
在hbm配置文件中设置
在类中使用注解
如果将lazy设置为false,代表类级别检索也使用立即检索。这时load与get就一样,都是立即检索。
如果对一个延迟代理对象进行初始化?
关联级别检索
        查询到某个对象,获得其关联的对象或属性,这种称为关联级别检索,例如
        c.getOrders().size()
        c.getName()
        对于关联级别检索我们就要研究其检索策略(抓取策略)
检索策略(抓取策略)抓取策略介绍
指的是查找到某个对象后,通过这个对象去查询关联对象的信息时的一种策略。
一对一 <one-to-one>
一对多(多对一) <set>下有<one-to-many>  <many-to-one>
多对多 <set>下有<many-to- many>
我们主要是在<set>与<many-to-one>或<one-to-one>上设置fetch  lazy
例如:查询一个客户,要关联查询它的订单
客户是一的一方,在客户中有set集合来描述其订单,在配置中我们是使用
<set>
        <one-to-many>
</set>..
可以在set标签上设置两个属性  fetch   lazy
Fetch主要描述的是SQL语句的格式(例如是多条,子查询,多表联查
Lazy 控制SQL语句何时发送
例如:在查询一个订单时,要查询客户信息
<many-to-one> 或<one-to-one>
也可以设置fetch  lazy
Fetch主要描述的是SQL语句的格式(例如是多条,子查询,多表联查
Lazy 控制SQL语句何时发送
总结:
讲解抓取策略
在两方面设置
<set fetch=”” lazy=””>
<many-to-one fetch=”” lazy=””>
<one-to-one>
注解配置抓取策略
问题:如何使用注解来设置
在<setse>设置的fetch与lazy可以使用下面注解来描述
在<many-to-one>或<one-to-one>上如何设置 fetch与lazy
set上的fetch与lazy
set上的fetch与lazy它主要是用于设置关联的集合信息的抓取策略。
Fetch可取值有:
1. SELECT 多条简单的sql   (默认值)
2. JOIN 采用迫切左外连接
3. SUBSELECT 将生成子查询的SQL
lazy可取值有:
1. TURE 延迟检索   (默认值)
2. FALSE 立即检索
3. EXTRA 加强延迟检索(及其懒惰)
第一种组合
会首先查询客户信息,当需要订单信息时,才会关联查询订单信息。
第二种组合
s
当查询客户信息时,就会将订单信息也查询,也就是说订单信息没有进行延迟。
第三种组合
当查询客户信息时,不会查询订单信息,当需要订单的个数时,也不会查询订单信息,
只会通过count来统计订单个数。
当我们使用size(),contains()或isEmpty()方法时不会查询订单信息。
第四种组合
如果fetch选择的是join方案,那么lazy它会失效。
生成SQl将采用的是迫切左外连接(left outer join fetch)
会立即查询。
第五种组合
会生成子查询,但是我们在查询订单时采用的是延迟加载。
第六种组合
会生成子查询,在查询客户信息时,就会将订单信息也查询出来
第七种组合
在查询订单时,只会根据情况来确定是否要订单信息,如果不需要,例如我们
程序中size操作,那么就会发出select count(*) from Order where c_customer_id=?
One的一言fetch与lazy
<set fetch lazy>它主要是设置在获取到一的一方时,如果去查询多的一方。
在<many-to-one>或<one-to-one>如果去查询对方。
对于程序 就是在多的一方如何查询一的主方信息
例如:获取到一个订单对象,要查询客户信息。
Fetch可取值:
        select 默认值,代表发送一条或多条简单的select语句
        join  发送一条迫切左外连接
lazy可取值
        false 不采用延迟加载
        proxy 默认值 是否采用延迟,需要另一方的类级别延迟策略来决定
        no-proxy 不用研究
第一种组合
注意:Customer的类级别延迟策略
当我们执行时,会首先发送一条sql只查询订单信息,客户信息会延迟,只有真正需要客户信息时,才会发送sql来查询客户信息.
第二种组合
注意:Customer的类级别延迟策略
当查询订单时,就会将客户信息也查询到,原因是Customer它的类级别延迟为false,也就是立即查询。
第三种组合
当查询订单时,不会对客户信息进行延迟,立即查询客户信息
第四种组合
如果fetch值为join,那么lazy失效。
会发送一条迫切左外连接来查询,也就立即查询。
批量抓取
我们在查询多个对象的关联对象时,可以采用批量抓取方式来对程序进行优化.
要想实现批量抓取:
可以在配置文件中 batch-size属性来设置
可以使用注解 @BatchSize(size=4)
可以采用批量抓取来解决N+1问题.
查询客户,查询订单
可以在客户配置文件中配置batch-size,是在<set>标签上
查询订单,查询客户
订单与客户,客户它是一个主表,订单是一个从表。
在设置批量抓取时都是在主表中设置
在配置文件中在主表的<calss>标签上设置batch-size
在注解使用中
注意:无论是根据哪一方来查询别一方,在进行批量抓取时,都是在父方来设置 ,
        如果是要查询子信息,那么我们是在<set>上来设置batch-size,如果是从子方来查询父方,
        也是在父方设置在<class>设置batch-size.
        
父与子区分:
        有外键的表是子(从关联方就是父(主)表
{:8_507:}
三大框架之Hibernate持久化类与主键生成策略-6
三大框架之Hibernate常用API-5
Java三大框架学习之Hibernate的配置详解-4(下)
JavaEE三大框架课堂笔记之Hibernate快速入门-4(上)
三大框架之Struts2-3
三大框架之Struts2-2
三大框架之Struts2-1
线程精进指南之线程池进阶
15个顶级Java多线程面试题及答案
Java String 面试题以及答案
Java IO流学习总结
14个你可能不知道的JavaScript调试技巧
Spring多个AOP执行先后顺序
认识JavaScript中的this


1 个回复

正序浏览
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马