1.数据表和实体
实体关系:客户和联系人之间是一对多的关系
主表:cst_customer,客户的cust_id作为联系人的外键
从表:cst_linkman,一个客户可以对应多个联系人
Customer对象中有linkMens集合
LinkMan对象中有customer对象
2.关联级别策略
有两种:集合关联策略、属性关联策略
集合策略:在Customer.hbm.xml中配置
fetch属性:决定加载策略:使用什么类型的sql语句加载集合数据
select:默认值,单表查询加载
join:使用多表查询加载集合
subselect:使用子查询加载集合
lazy属性:决定是否延迟加载
true:延迟加载(默认),懒加载
false:立即加载
extra:极其懒惰
<class name="Customer" table="cst_customer" lazy="true">
//这里lazy表时Customer对象使用时候才加载SQL语句执行
......各种其他配置
<set name="linkMens" lazy="extra" fetch="subselect">
<key column="lkm_cust_id"></key>
<one-to-many class="LinkMan" />
</set>
</class>
关联属性策略:在LinkMan.hbm.xml中配置
fetch:决定加载的SQL语句
select默认值,单表查询
join多表查询
lazy:决定加载时机
false:立即加载
proxy:加载时机由别人(Customer对象)替我决定(默认值)
<class name="LinkMan" table="cst_linkman" >
......其他配置
<many-to-one name="customer" column="lkm_cust_id" class="Customer"
fetch="select" lazy="proxy">
</many-to-one>
</class>
3.具体使用组合
3.1集合策略
//集合级别的关联
//fetch:select 单表查询
//lazy:true 使用时才加载集合数据
@Test
public void fun1(){
Session session=HibernateUtils.openSession();
Transaction tx=session.beginTransaction();
//----------------------------------
Customer c=session.get(Customer.class, 2l);//这个时候并没有加载LinkMan
Set<LinkMan> linkMens= c.getLinkMens();//这时也没打印
System.out.println(linkMens.size());//只加载count的语句
System.out.println(linkMens);//这个时候就把LinkMan加载出来了
//----------------------------------
tx.commit();
session.close();
}
//集合级别的关联
//fetch:select 单表查询
//lazy:false 立即加载加载集合数据
@Test
public void fun2(){
Session session=HibernateUtils.openSession();
Transaction tx=session.beginTransaction();
//----------------------------------
Customer c=session.get(Customer.class, 2l);//customer和LinkMan都加载了
Set<LinkMan> linkMens= c.getLinkMens();
System.out.println(linkMens.size());//也是只加载了count语句
System.out.println(linkMens);//这个时候就把LinkMan加载出来了
//----------------------------------
tx.commit();
session.close();
}
//集合级别的关联
//fetch:select 单表
//lazy:extra极其懒惰 其实跟懒惰没啥区别
@Test
public void fun3(){
Session session=HibernateUtils.openSession();
Transaction tx=session.beginTransaction();
//----------------------------------
Customer c=session.get(Customer.class, 2l);//只加载了customer
Set<LinkMan> linkMens= c.getLinkMens();//这时也没打印
System.out.println(linkMens.size());//只加载count的语句
System.out.println(linkMens);//这个时候就把LinkMan加载出来了
//----------------------------------
tx.commit();
session.close();
}
//集合级别的关联
//fetch:join 多表查询
//lazy:true|false|extra 失效。立即加载,一口气全查出来
@Test
public void fun4(){
Session session=HibernateUtils.openSession();
Transaction tx=session.beginTransaction();
//----------------------------------
Customer c=session.get(Customer.class, 2l);//全查出来了
Set<LinkMan> linkMens= c.getLinkMens();//
System.out.println(linkMens.size());//
System.out.println(linkMens);
//----------------------------------
tx.commit();
session.close();
}
//集合级别的关联
//fetch:subset 子查询
//lazy:true 懒加载
@Test
public void fun5(){
Session session=HibernateUtils.openSession();
Transaction tx=session.beginTransaction();
//----------------------------------
String hql="from Customer";
Query query= session.createQuery(hql);
List<Customer> list=query.list();//加载了customer
for(Customer c:list){
System.out.println(c);
System.out.println(c.getLinkMens().size());//直接加载了LinkMan(使用了子查询:select from where in (子查询))
System.out.println(c.getLinkMens());
}
//----------------------------------
tx.commit();
session.close();
}
//集合级别的关联
//fetch:subset 子查询
//lazy:false 立即加载
@Test
public void fun6(){
Session session=HibernateUtils.openSession();
Transaction tx=session.beginTransaction();
//----------------------------------
String hql="from Customer";
Query query= session.createQuery(hql);
List<Customer> list=query.list();//加载了customer、LinkMan(使用了子查询:select from where in (子)
for(Customer c:list){
System.out.println(c);
System.out.println(c.getLinkMens().size());
System.out.println(c.getLinkMens());
}
//----------------------------------
tx.commit();
session.close();
}
//集合级别的关联
//fetch:subset 子查询
//lazy:extra 极其懒惰
@Test
public void fun7(){
Session session=HibernateUtils.openSession();
Transaction tx=session.beginTransaction();
//----------------------------------
String hql="from Customer";
Query query= session.createQuery(hql);
List<Customer> list=query.list();//加载了customer
for(Customer c:list){
System.out.println(c);
System.out.println(c.getLinkMens().size());//只加载size语句
System.out.println(c.getLinkMens());//加载LinkMan的子查询
}
//----------------------------------
tx.commit();
session.close();
}
3.2关联属性策略
//属性的关联级别
//fetch:select单表查询
//lazy:proxy
//Customer为true:使用时候加载
//false时候就是立即加载,一口气加载LinkMan和Customer两个单表查询
public void fun1(){
Session session=HibernateUtils.openSession();
Transaction tx=session.beginTransaction();
//----------------------------------
LinkMan lm=session.get(LinkMan.class,1l);//加载LinkMan语句
Customer customer=lm.getCustomer();//没反应
System.out.println(customer);//加载Customer语句
//----------------------------------
tx.commit();
session.close();
}
//属性的关联级别
//fetch:join多表查询
//lazy:失效了额,因为是多表查询,一下子就要把两个都查出来
public void fun2(){
Session session=HibernateUtils.openSession();
Transaction tx=session.beginTransaction();
//----------------------------------
LinkMan lm=session.get(LinkMan.class,1l);//加载多表查询语句
Customer customer=lm.getCustomer();
System.out.println(customer);
//----------------------------------
tx.commit();
session.close();
}
4.结论
为了提高效率,fetch的选择上应该选择select(不要一下子全部查出来,会占用资源),lazy的取值应该选择true(懒加载,用到才加载(这里就用到了代理的机制来强化实体类的功能:使用实体的某个未初始化的属性的时候会自动去执行sql查询))。而这两个属性都是默认值。
5.问题
no-session问题怎么解决:
扩大session的作用范围,使用Filter拦截器进行扩展