2009年2月27日 Hibernate-Version: 3.2.5.ga
=================================================================================================
==================================================================================================
类级别(class的lazy属性,3.x默认为true,2.x默认为false)
受影响方法:get(),load()
延迟检索
立即检索
lazy
true
false
get():总是使用立即检索,没有数据则返回空
load():lazy=true延迟检索,调用getXX()(非getOID())时进行查询,没有数据则抛出异常
lazy=false立即检索,没有数据则抛出异常
==================================================================================================
==================================================================================================
关联级别1(<one-to-one>/<many-to-one>)
outer-join:true | false | auto [Hibernate3已经不赞成使用,使用fetch代替]
fetch:join | select(默认:select)
lazy:false | proxy | no-proxy(默认:proxy)
主键表class lazy:true | false(默认:true)
受影响的方法:HQL,QBC,SQLQuery,get()/load()
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
fetch
lazy
主键表class lazy
检索策略
检索方式
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
select
false
true/false
立即检索(n+1次查询)
所有
no-proxy/proxy
true
延迟检索(n+1次查询)
所有
false
立即检索(n+1次查询)
所有
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
join
false
true/false
inner join
QBC,get()/load()
立即检索(n+1次查询)
HQL,SQLQuery
no-proxy/proxy
false
inner join
QBC,get()/load()
立即检索(n+1次查询)
HQL,SQLQuery
true
inner join
QBC,get()/load()
延迟检索(n+1次查询)
HQL,SQLQuery
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
注:1,n+1次查询问题解决办法:
A:可以改用连接查询fetch=join
B:设置批量抓取(batch-size),设置主键表class的batch-size属性,建议3-10之间,这时会使用in(?,?,?)来减少查询语句
2,lazy="proxy"单点关联是经过代理的。lazy="no-proxy"指定此属性应该在实例变量第一次被访问时应该延迟抓取
(fetche lazily)(需要运行时字节码的增强)。lazy="false"指定此关联总是被预先抓取。
==================================================================================================
==================================================================================================
关联级别2(<set>)
outer-join:true | false | auto [Hibernate3已经不赞成使用,使用fetch代替]
fetch:join | select | subselect(默认:select)
lazy:true | false | extra(默认:true)
受影响的方法:HQL,QBC,SQLQuery,get()/load()
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
fetch
lazy
检索策略
检索方式
select
extra/true
延迟检索(n+1次查询)
所有
false
立即检索(n+1次查询)
所有
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
join
true/extra
left join fetch
QBC,get()/load()
延迟检索(n+1次查询)
HQL,SQLQuery
false
left join fetch
QBC,get()/load()
立即检索(n+1次查询)
HQL,SQLQuery
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
subselect
false
立即检索(n+1次查询)
get()/load(),SQLQuery
立即检索(batch fetch)
HQL,QBC(使用in子查询进行批量检索)
true/extra
延迟检索(n+1次查询)
get()/load(),SQLQuery
延迟检索(batch fetch)
HQL,QBC(使用in子查询进行批量检索)
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
注:1,1,n+1次查询问题解决办法:
A:可以改用连接查询fetch=join
B:设置批量抓取(batch-size),设置<set>的batch-size属性,建议3-10之间,这时会使用in(?,?,?)来减少查询语句
C:设置fetch=subselect,这时只会出现两条SQL语句,第1条SQL查询主键表数据,第2条SQL使用子查询in来查询相关联数据
2,subselect:在检索集合中元素时subselect可以把n+1的检索变为1+1,即一共只出现2条SQL语句,示例:
hql:from Customers
sql://查询customers
select id, username, password, address, email, age from customers
//使用子查询in来查询相关联的orders
select o.id,o.customerid,o.productid,o.amount,o.buytime from orders o where o.customerid in (select id from customers)
3,extra:一种比较聪明的延迟检索策略,即调用集合的size/contains等方法的时候,hibernate并不会去加载整个集合的数据,
而是发出一条聪明的SQL语句,以便获得需要的值,只有在真正需要用到这些集合元素对象数据的时候,才去发出查询语
句加载所有对象的数据,
示例A:
List<Customers> list = session.createQuery("from Customers").list();
for (Customers order : list)
System.out.println(order.getOrderses().size());
sql如下:
//查询customers
select id, username, password, address, email, age from customers
//因为调用的是list.size(),所以执行以下SQL
select count(id) from orders where customerid =?
select count(id) from orders where customerid =?
select count(id) from orders where customerid =?
示例B:
List<Customers> list = session.createQuery("from Customers").list();
for (Customers order : list) {
Orders o = new Orders();
o.setId(1001L);
System.out.println(order.getOrderses().contains(o));
}
sql如下:
//查询customers
select id, username, password, address, email, age from customers
//因为调用的是list.contains(),所以执行以下SQL
select 1 from orders where customerid =? and id =?
select 1 from orders where customerid =? and id =?
select 1 from orders where customerid =? and id =?
==================================================================================================
==================================================================================================
注:1,只有QBC,get()/load()支持配制文件中的inner join,其它不支持
2,不管使用何种设置,HQL语句中都可显示使用连接抓取
==================================================================================================
==================================================================================================
联合查询
HQL提供了以下几种联合查询机制:
inner join fetch,left join fetch,right join fetch,full join
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
A,inner join fetch(实际上是SQL中的显示内连接:inner join on)
hql="from TPerson tp inner join fetch tp.address";
inner join 返回所有满足关联条件的记录组合,对应的sql语句是:
sql="select * from t_person tp inner join t_address addr on tp.id=addr.person_id";
注:“inner join fetch ”中的fetch关键字表明TAddress对象读出后立即填充到对应的TPerson对象(address属性)中。如果
忽略该关键字,则得到的结果集中,每个条目都是一个Object数组,包括了一个TPerson对象及其对应的TAddress对象
以下的fetch都是这个意思。
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
B、left join fetch(实际上是SQL中的左外连接:left outer join on)
hql="from TPerson tp left join fetch tp.address";
返回的结果集中,包含了t_person表(HQL中位于左侧的表)中的所有记录,及其对应的地址信息,如无则以NULL代替。
sql="select * from t_person tp left outer join t_address addr on tp.id=addr.person_id";
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
C、right join fetch(实际上是SQL中的右外连接:right outer join on)
hql="from TPerson tp right join tp.address";
与left outer join相反,right outer join 返回的是t_address(HQl中位于右侧的表)中的所有记录及其对应的t_person记录,
如无则以NULL代替。
注:fetch关键字只对inner join和left outer join有效。对right outer join 而言,
1>,hql="from TPerson tp right join tp.address",由于作为关联对象容器的t_person对象可能为null,所以也就无法通过
关键字fetch强制Hibernate进行集合填充操作。意味着只能通过对返回集合中的各个对象数组进行处理,获取所需数据。
2>,hql="from Address a right join a.person",而此时是可以使用fetch的,使用fetch时,集合元素为Address对象,否则为数组
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
D、full join(实际上是SQL中的交叉连接)
hql="from TPerson tp full join tp.address";
报错:org.hibernate.AssertionFailure: undefined join type 23(未解决:mysql5)
返回连接表中所有数据的笛卡尔积,结果集数:person表总条数*address表总条数。
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
E:子查询
hql="from Tperson tp where (select count(*) from tp.address)>1";
sql="select ...... from t_person tp where ((select count(*) from t_address addr where tp.id=addr.person_id)>1)";
HQL中,子查询必须出现在where子句中,且必须以一对圆括号包围。
此处转载并修改部分说明:http://blog.csdn.net/fhwbj/archive/2008/12/16/3527950.aspx
==================================================================================================
==================================================================================================
连接查询
customers(id,name) orders(id,name,price,customer_id)
1.交叉连接(cross join,full join)
不带on子句,返回连接表中所有数据的笛卡尔积,结果集数:customers总条数*orders总条数
select * from customers,orders
select * from customers cross join orders
select * from customers full join orders
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2.内连接(inner join)
返回连接表中符合连接条件及查询条件的行
1>,显示内连接(select ... from 表1 inner join 表2 on 条件 where ...)
select * from customers c inner join orders o on c.id=o.customer_id
2>.隐式内连接(select ... from 表1,表2 where 条件)
select * from customers c,orders o where c.id=o.customer_id;
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3.外连接(outer join)
1>,左外连接(select ... from 左表 left outer join 右表 on 条件 where ...)
返回左表所有数据和右表符合条件的数据
select * from customers c left outer join orders o on c.id=o.customer_id where c.id=6
2>,右外连接(select ... from 左表 right outer join 右表 on 条件 where ...) 返回右表所有数据和左表符合条件的数据
select * from customers c right outer join orders o on c.id=o.customer_id where c.id=7