08-Hibernate类级别加载策略,关联级别策略
-
类级别加载策略
-
get方法:立即加载。执行方法时立即发送SQL语句查询结果
<class name="Customer" table="cst_customer" lazy="true">
@Test //get方法:立即加载。执行方法时立即发送SQL语句查询结果 public void fun1(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); //--------------------------------------------------------- Customer c = session.get(Customer.class, 2l); System.out.println(c); //---------------------------------------------------------- tx.commit(); session.close(); }
-
load方法(默认):是在执行时,不发送任何sql语句,返回一个对象,使用该对象时,才执行查询。
- 延迟加载:仅仅获取没有使用,不会查询,在使用时才会进行查询
- 是否对类进行延迟加载,: 可以通过在class元数据上配置lazy属性来控制
- lazy:true 加载时,不查询,使用时才查询
- lazy:false 加载时立即查询
- 结论:为了提高效率。建议使用延迟加载(懒加载)
- 注意:使用懒加载时要确保调用属性加载数据时,session还是打开的,否则会抛出org.hibernate.LazyInitializationException: could not initialize proxy - no Session
@Test //load方法(默认):是在执行时,不发送任何sql语句,返回一个对象,使用该对象时,才执行查询。 //延迟加载:仅仅获取没有使用,不会查询,在使用时才会进行查询 //是否对类进行延迟加载,: 可以通过在class元数据上配置lazy属性来控制 //lazy:true 加载时,不查询,使用时才查询 //lazy:false 加载时立即查询 public void fun2(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); //--------------------------------------------------------- Customer c = session.load(Customer.class, 2l); System.out.println(c); //---------------------------------------------------------- tx.commit(); session.close(); }
-
-
关联级别策略
-
集合策略
-
lazy属性:决定是否延迟加载
- true(默认值): 延迟加载,使用时,才加载集合数据
- false: 立即加载
- extra: 及其懒惰
-
fetch属性: 决定加载策略,使用什么类型的sql语句加载集合
- select(默认值): 单表查询加载
- join:使用多表查询加载集合
- subselect:使用子查询加载集合
<set name="linkMens" lazy="extra" fetch="subselect">
//关联级别延迟加载&抓取策略 public class Demo { @Test //集合级别的关联 //fecth:select //lazy:true 使用时,才加载集合数据 public void fun1(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); //--------------------------------------------------------- Customer c = session.get(Customer.class, 2l); Set<LinkMan> linkmans = c.getLinkMans();//级别关联 System.out.println(linkmans); //---------------------------------------------------------- tx.commit(); session.close(); } @Test //集合级别的关联 //fecth:select //lazy:false 立即加载集合数据 public void fun2(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); //--------------------------------------------------------- Customer c = session.get(Customer.class, 2l); Set<LinkMan> linkmans = c.getLinkMans();//级别关联 System.out.println(linkmans); //---------------------------------------------------------- tx.commit(); session.close(); } @Test //集合级别的关联 //fecth:select //lazy:extra 极其懒惰,与懒惰加载结果基本一致,如果只获得集合的size,只会查询集合的size(count语句) public void fun3(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); //--------------------------------------------------------- Customer c = session.get(Customer.class, 2l); Set<LinkMan> linkmans = c.getLinkMans();//级别关联 System.out.println(linkmans.size()); System.out.println(linkmans); //---------------------------------------------------------- tx.commit(); session.close(); } @Test //集合级别的关联 //fecth:join 多表查询 //lazy:true|false|extra 失效。立即加载 public void fun4(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); //--------------------------------------------------------- Customer c = session.get(Customer.class, 2l); Set<LinkMan> linkmans = c.getLinkMans();//级别关联 System.out.println(linkmans.size()); System.out.println(linkmans); //---------------------------------------------------------- tx.commit(); session.close(); } @Test //集合级别的关联 //fecth:subselect 子查询 //lazy:true 懒加载 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(); for(Customer c:list){ System.out.println(c); System.out.println(c.getLinkMans().size()); System.out.println(c.getLinkMans().size()); } //---------------------------------------------------------- tx.commit(); session.close(); } @Test //集合级别的关联 //fecth:subselect 子查询 //lazy:false 立即加载 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(); for(Customer c:list){ System.out.println(c); System.out.println(c.getLinkMans().size()); System.out.println(c.getLinkMans().size()); } //---------------------------------------------------------- tx.commit(); session.close(); } @Test //集合级别的关联 //fecth:subselect 子查询 //lazy:extra 极其懒惰加载 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(); for(Customer c:list){ System.out.println(c); System.out.println(c.getLinkMans().size()); System.out.println(c.getLinkMans().size()); } //---------------------------------------------------------- tx.commit(); session.close(); } }
-
-
对象策略
结论:为了提高效率,fetch的选择上应该选择select,lazy的取值应该选择true(全部使用策略值)
-
lazy属性:决定是否延迟加载
- false : 立即加载
- proxy : 由customer的类级别加载策略决定
-
fetch属性: 决定加载策略,使用什么类型的sql语句加载集合
- select:使用单表查询
- join:多表查询,(当使用fetch属性使用join时,lazy属性处于失效状态)
<many-to-one name="customer" column="lkm_cust_id" class="com.qingzi.domain.Customer" lazy="false" fetch="join"></many-to-one>
//关联级别 延迟加载 & 抓取策略 public class Demo2 { @Test //集合级别的关联 //fetch:select 单表查询 //lazy:proxy //customer -true 使用懒加载 public void fun1(){ 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(); } @Test //集合级别的关联 //fetch:select 单表查询 //lazy:proxy //customer -false 立即加载 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(); } @Test //集合级别的关联 //fetch:join 多表查询 //lazy:失效状态 public void fun3(){ 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(); } }
-
-
no-session问题的解决
扩大session的作用范围(如图所示)
-
抓取策略优化
- batch-size: 抓取集合的数量为3,抓取客户集合时,一次抓取几个客户的联系人的集合
<set name="linkMens" batch-size="3">
//抓取数量 public class Demo { @Test //集合级别的关联 //fecth:select //lazy:true 使用时,才加载集合数据 public void fun1(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); //--------------------------------------------------------- String hql = "from Customer"; Query query = session.createQuery(hql); List<Customer> list = query.list(); for(Customer c: list){ System.out.println(c.getLinkMans()); } //---------------------------------------------------------- tx.commit(); session.close(); } }
-