hibernate抓取策略
来源:互联网 发布:模糊pid控制算法程序 编辑:程序博客网 时间:2024/06/05 14:49
抓取策略(fetching strategy)是指:当应用程序需要在(Hibernate实体对象图的)关联关系间进行导航的时候,Hibernate如何获取关联对象的策略。抓取策略可以在O/R映射的元数据中声明,也可以在特定的HQL或条件查询(Criteria Query)中重载声明。
Hibernate定义了如下几种抓取策略:
1、连接抓取(Join fetching)--Hibernate通过在select语句中使用outer join(外链接)来获得对象的关联实例或者关联集合。这时lazy无效。
2、查询抓取(select fetching)--另外发送一条select语句抓取当前对象的关联实体或集合。除非你显示的指定lazy=false禁止延迟抓取,否则只有当你真正访问关联关系的时候,才会执行第二条select语句。
3、子查询抓取(Subselect fetching)--另外发送一条select语句抓取在前面查询到(或者抓取到)的所有实体对象的关联集合。除非你显示的指定lazy=false禁止延迟抓取,否则只有当你真正访问关联关系的时候,才会执行第二条select语句。
4、批量抓取(Batch fetching)--对查询抓取的优化方案,通过指定一个主键或外键列表,Hibernate使用单条select语句获取一批对象实例或集合。
下面我们通过项目案例来简单了解下这几种策略
java项目结构如下:
该项目所有代码跟上一节《hibernate加载策略之lazy》一样,可以参考。
查询抓取(select fetching)
在多的一端设置fetch
Book.hbm.xml配置文件
<hibernate-mapping package="com.test.pojo"> <class name="Book" table="book"> <id name="id"> <generator class="identity" /> </id> <many-to-one name="category" class="Category" column="category_id" cascade="save-update" lazy="proxy" fetch="select"/> <property name="author" /> <property name="name" column="book_name" /> <property name="price" /> <property name="pubDate" /> </class> </hibernate-mapping>
在HibernateTest类中添加代码
@Testpublic void testLoad1(){Session session=HibernateUtil.getSession();Transaction tx=session.beginTransaction();Book book=(Book) session.get(Book.class, 1);System.out.println(book.getName());System.out.println(book.getCategory().getName());tx.commit();HibernateUtil.closeSession();}
断点执行,当执行到
System.out.println(book.getName());打印sql语句如下
Hibernate: select book0_.id as id1_1_0_, book0_.category_id as category2_1_0_, book0_.author as author3_1_0_, book0_.book_name as book_nam4_1_0_, book0_.price as price5_1_0_, book0_.pubDate as pubDate6_1_0_ from book book0_ where book0_.id=?
当执行到
System.out.println(book.getCategory().getName());打印sql语句如下
Hibernate: select category0_.id as id1_0_0_, category0_.name as name2_0_0_ from Category category0_ where category0_.id=?当我们把Book.hbm.xml中的lazy改为false,如下
<many-to-one name="category" class="Category" column="category_id" cascade="save-update" lazy="false" fetch="select"/>断点执行testLoad1,当执行到
Book book=(Book) session.get(Book.class, 1);打印sql语句如下
Hibernate: select book0_.id as id1_1_0_, book0_.category_id as category2_1_0_, book0_.author as author3_1_0_, book0_.book_name as book_nam4_1_0_, book0_.price as price5_1_0_, book0_.pubDate as pubDate6_1_0_ from book book0_ where book0_.id=?Hibernate: select category0_.id as id1_0_0_, category0_.name as name2_0_0_ from Category category0_ where category0_.id=?
下面我们在一的一端设置fetch
Category.hbm.xml代码
<hibernate-mapping package="com.test.pojo"> <class name="Category" > <id name="id" > <generator class="identity" /> </id> <property name="name" /> <set name="books" inverse="true" lazy="extra" fetch="select"> <key> <column name="category_id" /> </key> <one-to-many class="Book" /> </set> </class> </hibernate-mapping>
断点执行HibernateTest类中的testGet方法
@Testpublic void testGet(){Session session=HibernateUtil.getSession();Transaction tx=session.beginTransaction();Category category=(Category) session.get(Category.class, 1);System.out.println("分类名:"+category.getName());for(Iterator<Book> iter=category.getBooks().iterator();iter.hasNext();){System.out.println(iter.next().getName());}tx.commit();HibernateUtil.closeSession();}
断点执行到
Category category=(Category) session.get(Category.class, 1);打印sql语句如下
Hibernate: select category0_.id as id1_0_0_, category0_.name as name2_0_0_ from Category category0_ where category0_.id=?执行到
System.out.println(iter.next().getName());打印sql语句如下
Hibernate: select books0_.category_id as category2_0_0_, books0_.id as id1_1_0_, books0_.id as id1_1_1_, books0_.category_id as category2_1_1_, books0_.author as author3_1_1_, books0_.book_name as book_nam4_1_1_, books0_.price as price5_1_1_, books0_.pubDate as pubDate6_1_1_ from book books0_ where books0_.category_id=?从上面可以看出来,get方法,当时就查询了Category表的sql语句,当需要查询Book的数据时,才会执行book的数据库表信息。
连接抓取(Join fetching)
先看在多的一端设置fetch
将Book.hbm.xml中的fetch设为join,lazy设为proxy,如下
<many-to-one name="category" class="Category" column="category_id" cascade="save-update" lazy="proxy" fetch="join"/>执行testLoad1,打印信息如下:
Hibernate: select book0_.id as id1_1_0_, book0_.category_id as category2_1_0_, book0_.author as author3_1_0_, book0_.book_name as book_nam4_1_0_, book0_.price as price5_1_0_, book0_.pubDate as pubDate6_1_0_, category1_.id as id1_0_1_, category1_.name as name2_0_1_ from book book0_ left outer join Category category1_ on book0_.category_id=category1_.id where book0_.id=?读者文学由上面可以看到,在需要book的信息时,sql语句使用 left outer join 把Category表中的信息也查询了出来。
再来从一的一端来查询
将Category.hbm.xml中的fetch设为join,lazy默认为true
<set name="books" inverse="true" fetch="join">执行testLoad代码
@Testpublic void testLoad(){Session session=HibernateUtil.getSession();Transaction tx=session.beginTransaction();Category category=(Category) session.get(Category.class, 1);System.out.println("分类名:"+category.getName());System.out.println("对应的书大小:"+category.getBooks().size());tx.commit();HibernateUtil.closeSession();}打印信息如下
Hibernate: select category0_.id as id1_0_0_, category0_.name as name2_0_0_, books1_.category_id as category2_0_1_, books1_.id as id1_1_1_, books1_.id as id1_1_2_, books1_.category_id as category2_1_2_, books1_.author as author3_1_2_, books1_.book_name as book_nam4_1_2_, books1_.price as price5_1_2_, books1_.pubDate as pubDate6_1_2_ from Category category0_ left outer join book books1_ on category0_.id=books1_.category_id where category0_.id=?分类名:文学对应的书大小:1
从一的一端也是使用left outer join方法把book表中的数据一起查询出来了。
接下来我们把Book.hbm.xml和Category.hbm.xml中的lazy和fetch都去掉,执行testLoad2,代码如下
@Testpublic void testLoad2(){Session session=HibernateUtil.getSession();Transaction tx=session.beginTransaction();List<Category> list=session.createCriteria(Category.class).list();System.out.println("类型个数:"+list.size());for(Category cate:list){System.out.println(cate.getName()+"---书籍本数:"+cate.getBooks().size());}tx.commit();HibernateUtil.closeSession();}打印sql语句如下
Hibernate: select this_.id as id1_0_0_, this_.name as name2_0_0_ from Category this_类型个数:6Hibernate: select books0_.category_id as category2_0_0_, books0_.id as id1_1_0_, books0_.id as id1_1_1_, books0_.category_id as category2_1_1_, books0_.author as author3_1_1_, books0_.book_name as book_nam4_1_1_, books0_.price as price5_1_1_, books0_.pubDate as pubDate6_1_1_ from book books0_ where books0_.category_id=?文学---书籍本数:1Hibernate: select books0_.category_id as category2_0_0_, books0_.id as id1_1_0_, books0_.id as id1_1_1_, books0_.category_id as category2_1_1_, books0_.author as author3_1_1_, books0_.book_name as book_nam4_1_1_, books0_.price as price5_1_1_, books0_.pubDate as pubDate6_1_1_ from book books0_ where books0_.category_id=?科幻---书籍本数:1Hibernate: select books0_.category_id as category2_0_0_, books0_.id as id1_1_0_, books0_.id as id1_1_1_, books0_.category_id as category2_1_1_, books0_.author as author3_1_1_, books0_.book_name as book_nam4_1_1_, books0_.price as price5_1_1_, books0_.pubDate as pubDate6_1_1_ from book books0_ where books0_.category_id=?言情---书籍本数:1Hibernate: select books0_.category_id as category2_0_0_, books0_.id as id1_1_0_, books0_.id as id1_1_1_, books0_.category_id as category2_1_1_, books0_.author as author3_1_1_, books0_.book_name as book_nam4_1_1_, books0_.price as price5_1_1_, books0_.pubDate as pubDate6_1_1_ from book books0_ where books0_.category_id=?历史---书籍本数:1Hibernate: select books0_.category_id as category2_0_0_, books0_.id as id1_1_0_, books0_.id as id1_1_1_, books0_.category_id as category2_1_1_, books0_.author as author3_1_1_, books0_.book_name as book_nam4_1_1_, books0_.price as price5_1_1_, books0_.pubDate as pubDate6_1_1_ from book books0_ where books0_.category_id=?漫画---书籍本数:1Hibernate: select books0_.category_id as category2_0_0_, books0_.id as id1_1_0_, books0_.id as id1_1_1_, books0_.category_id as category2_1_1_, books0_.author as author3_1_1_, books0_.book_name as book_nam4_1_1_, books0_.price as price5_1_1_, books0_.pubDate as pubDate6_1_1_ from book books0_ where books0_.category_id=?悬疑---书籍本数:1从上面的sql语句可以看出sql语句重复
子查询抓取(Subselect fetching)
我们在Category.hbm.xml中加上fetch=subselect
<set name="books" inverse="true" fetch="subselect">继续执行testLoad2,打印sql语句如下
Hibernate: select this_.id as id1_0_0_, this_.name as name2_0_0_ from Category this_类型个数:6Hibernate: select books0_.category_id as category2_0_1_, books0_.id as id1_1_1_, books0_.id as id1_1_0_, books0_.category_id as category2_1_0_, books0_.author as author3_1_0_, books0_.book_name as book_nam4_1_0_, books0_.price as price5_1_0_, books0_.pubDate as pubDate6_1_0_ from book books0_ where books0_.category_id in ( select this_.id from Category this_ )文学---书籍本数:1科幻---书籍本数:1言情---书籍本数:1历史---书籍本数:1漫画---书籍本数:1悬疑---书籍本数:1
一次性将所有的分类Category的数据全部查询出来。
假设现在我想查询Category的id是1,3,5的数据,那么方法testLoad2的代码如下
@Testpublic void testLoad2(){Session session=HibernateUtil.getSession();Transaction tx=session.beginTransaction();List<Category> list=session.createCriteria(Category.class).add(Restrictions.in("id", new Integer[]{1,3,5})).list();System.out.println("类型个数:"+list.size());for(Category cate:list){System.out.println(cate.getName()+"---书籍本数:"+cate.getBooks().size());}tx.commit();HibernateUtil.closeSession();}打印sql语句如下
Hibernate: select this_.id as id1_0_0_, this_.name as name2_0_0_ from Category this_ where this_.id in ( ?, ?, ? )类型个数:3Hibernate: select books0_.category_id as category2_0_1_, books0_.id as id1_1_1_, books0_.id as id1_1_0_, books0_.category_id as category2_1_0_, books0_.author as author3_1_0_, books0_.book_name as book_nam4_1_0_, books0_.price as price5_1_0_, books0_.pubDate as pubDate6_1_0_ from book books0_ where books0_.category_id in ( select this_.id from Category this_ where this_.id in ( ?, ?, ? ) )文学---书籍本数:1言情---书籍本数:1漫画---书籍本数:1
批量抓取(Batch fetching)
数据量大的时候采用此方法有意义,数据量小时,采用此方法效果不明显。
- Hibernate抓取策略
- Hibernate的抓取策略
- Hibernate Fetch 抓取策略
- hibernate 抓取策略
- Hibernate中的抓取策略
- hibernate抓取策略
- Hibernate------抓取策略
- Hibernate 抓取策略
- hibernate抓取策略
- hibernate抓取策略
- hibernate---->抓取策略
- hibernate 抓取策略
- Hibernate的抓取策略
- Hibernate抓取策略
- hibernate抓取策略
- hibernate 抓取策略fetch
- Hibernate-抓取策略
- hibernate抓取策略
- 【收藏】Edraw Max(亿图图示)软件快捷键大全
- shiro标签获取当前登陆的用户名问题
- java常用的日期函数
- 思岚科技共邀你参加2017世界机器人大会
- HDOJ2112 最短路简单题
- hibernate抓取策略
- svn入门
- Base64编码及其作用
- HTML笔记(一)bootstrap之网格
- 49. Group Anagrams
- python之网页自动打卡
- Spring 报错提示:Failed to read candidate component class
- hibernate
- radioButton单选按钮的实现