Hibernate深入

1.no-session 问题

1.1 no-session问题的产生
异常名称:org.hibernate.LazyInitializationException: could not initialize proxy - no Session
1、no-session问题产生的原因是获取数据使用延迟加载数据的方式,当使用数据前关闭session的,再使用数据时,数据不会加载,进而报错
1.2 解决no-session问题
1、在session关闭之前,直接使用数据,这时数据会加载完成,此后再使用数据就是完整数据
1.3 数据的抓取策略
提高执行效率以及解决no-session的问题
常用的抓取策略
抓取策略可以配置在类上,表示类的抓取策略,也可以配置到set或者one-to-many等上表示对方的抓取策略
lazy属性在one-to-many中有三个属性   false、proxy
many-to-many 有三个属性  false,true,extra
1、set节点中配置抓取策略
    fetch:"join" 抓取时使用左外连接       使用join可以提高查询效率,因为执行的sql语句相对较少
    fetch:"select"  抓取时使用多条SQL语句    相比于join效率低一些
    使用HQL/SQL查询 fetch="join"失效,lazy属性有效,因为HQL和SQL已经指定了语句,按指定的语句操作
    使用get/load或者QBC 查询时,使用hibernate底层的语句查询   lazy属性无效,fetch属性有效    

    lazy="false"是否懒加载,延迟加载   false表示不延迟加载  true表示延迟加载    extra  极其懒惰,除查询属性外,查询其他的内容,是不查询属性。
    lazy="proxy"   代表代理,就是由对方来执行抓取策略,也即由对方的抓去策略来执行
    fetch决定的是sql语句的格式 ,lazy决定的是sql语句出现的时机
2、many-to-one   节点中配置抓取策略
抓取策略是当应用程序需要在(Hibernate实体对象图的)关联关系间进行导航的时候, Hibernate如何获取关联对象的策略。
抓取策略包括:
    查询时机:延迟加载、立即加载
    查询方式:单表查询、多表查询

抓取策略可以在hbm映射文件中声明,也可以通过在HQL 语句定义。
QBC、get查询方式使用hbm映射文件中定义的抓取策略进行。
Hql不能使用hbm文件中定义的抓取策略,它通过迫切内连接、迫切外连接方式实现抓取策略。

1.3.2   类抓取策略
    设置类级别抓取策略 ,修改 hbm文件 <class>元素 lazy属性,默认为true延迟加载,修改为false 立即加载。
    如果修改为false则get方法和load方法一样都是立即加载。 
    如果采用默认true,get立即检索,load延迟检索。

1.3.3   关联抓取策略
    当通过对象导航方式查询关联对象时可以设置数据抓取策略。比如:调用 customer.getCstLinkmans()获取cstLinkmans信息时通过抓取策略修改数据的获取方式。

1.3.3.1 一对多、多对多
<set> 元素提供 lazy属性 和 fetch 用于设置 抓取策略


Fetch(默认select) Lazy(默认true)    策略
join    True    采用迫切左外连接
join    false   采用迫切左外连接
select  true    延迟检索
select  false   立即检索


   fetch=join 
fetch="join"实现批量抓取。
如果fetch设置为join,lazy不起作用。
get、QBC、HQL都支持fetch方式。
get和QBC方式会采用左外连接SQL方式,fetch=join时会忽略lazy。

测试:查询客户关联查询联系人,设置fetch=join


   fetch=select (默认值 )
生成多条SQL语句
lazy=true 延迟加载 (默认值 )
lazy=false 立即加载 

测试:查询客户关联查询联系人,设置fetch=select lazy=true、fetch=select lazy=false


1.3.3.2 多对一

多对一, hbm采用 <many-to-one>元素,提供lazy属性和fetch属性,用来配置抓取策略 
Fetch(默认select) Lazy(默认proxy)   策略
join    True    采用迫切左外连接
join    false   采用迫切左外连接
select  false   立即检索
select  proxy   按照class中设置lazy执行
Class中设置为 true则为延迟加载
Class中设置为false则为立即加载


   fetch=join 采用迫切左外连接查询

测试:查询客户关联查询客户来源,设置fetch=join


   fetch=select (默认值)
产生多条SQL语句 
    Lazy=false表示立即加载
    lazy=proxy表示:
    按照class (被关联对象的class) 中设置lazy执行
    Class中设置为 true则为延迟加载
    Class中设置为false则为立即加载

测试:查询客户关联查询客户来源,设置fetch=select lazy=proxy、fetch=select lazy=false

3 批量策略

N+1问题:
    比如说查询customer表时,查询所有cutomer,会输出一条sql语句,同时查询其对应的linkman时,会每条customer都查询一次sql语句,会产生N+1条sql语句,
    效率相对较慢,可以使用批量增加策略
解/决方案在 set节点上配置batch-sezi="10",这样表示一次查询10个客户的联系人,减少了SQL语句,大大提高执行了效率

4 HQL语句的加强

1、String hql = "from Customer" 语句正确  返回的是所有Customer对象
2、String hql="from Customer where custId=3" 语句正确查询为id=3的Customer对象
3、String hql ="select * from Customer" 语句错误,因为类中没有*对应的属性
4、String hql = "select custName from Customer" 语句正确 返回的结果是 custName  String类型
5、String hql = "select custId,custName from Customer" 语句正确,返回的结果是数组,第一个元素为custID,第二个为custName
6、String hql = "select new Customer() from Customer" 语句错误
7、String hql = "select new Customer(custId) from Customer" 错误,必须要有对应的构造函数
8、String hql = " from Customer as c order by c.custId";正确,返回的是Customer对象并排序
9、String hql = "from java.lang.Object" 多态查询,查询所有的持久化对象
10、String hql = " from Customer c inner join c.linkmans" 语句正确、显示外连接
11、String hql = "from Customer c,LinkMan l where c.custId=L.customer.custId"语句正确、隐式外连接  
12、String hql = " from Customer c inner join LinkMan l on c.custId=L.customer.custId" 语句错误
    进行内联接操作时,虽然查询了linkman,但并没有将linkman赋值到customer中,使用连接查询,返回的是数组,两个元素分别为对应的对象
13、配合fetch迫切 使用  String hql = " from Customer c inner join fetch c.linkmans"
    将查询到的linkman封装到对应的customer中,返回的结果是customer对象
14、 String hql = "  from Customer c left  join fetch c.linkMans";使用左外连接进行查询的时候如果一个客户有多个联系人,这个客户就会
    查询多次,使用distinct去重就可以了  String hql = "select distinct c from Customer c left join fetch c.linkMans ";

你可能感兴趣的:(Hibernate)