博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
hibernate抓取策略fetch
阅读量:4291 次
发布时间:2019-05-27

本文共 17489 字,大约阅读时间需要 58 分钟。

         抓取策略(fetching strategy)是指:当应用程序需要在(Hibernate实体对象图的)关联关系间经行导航的时候,hibernate如何获取关联对象的策略。抓取策略可以在O/R映射的元数据中声明,也可以在特定的HQL 或条件查询(Criteria Query)中重载声明。

Hibernate3 定义了如下几种抓取策略:

连接抓取(Join fetching) - Hibernate通过 在SELECT语句使用OUTER JOIN(外连接)来 获得对象的关联实例或者关联集合,这种情况lazy无效。

查询抓取(Select fetching) - 另外发送一条SELECT 语句抓取当前对象的关联实体或集合。除非你显式的指定lazy="false"禁止 延迟抓取(lazy fetching),否则只有当你真正访问关联关系的时候,才会执行第二条select语句。

子查询抓取(Subselect fetching) - 另外发送一条SELECT 语句抓取在前面查询到(或者抓取到)的所有实体对象的关联集合。除非你显式的指定lazy="false" 禁止延迟抓取(lazy fetching),否则只有当你真正访问关联关系的时候,才会执行第二条select语句。

批量抓取(Batch fetching) - 对查询抓取的优化方案, 通过指定一个主键或外键列表,Hibernate使用单条SELECT语句获取一批对象实例或集合。  

下面来分别介绍这几种抓取

查询抓取(Select fetching)

项目结构如图

所有的代码和上一节《》中的代码一样,可以参考,

现在多的一端设置fetch

Book.hbm.xml代码:

Category.hbm.xml代码:

HibernateTest中TestCreateDB代码:

@Test	public void testCreateDB() {		Configuration cfg = new Configuration().configure();		SchemaExport se = new SchemaExport(cfg);		// 第一个参数:是否生成ddl脚本		// 第二个参数:是否执行到数据库中		se.create(true, true);	}
使用Junit4执行,重新生成数据库表。

控制台打印的sql语句如下:

alter table t_book         drop         foreign key FK_cm584cq6cv5yht4jrqal0ocaq    drop table if exists Category    drop table if exists t_book    create table Category (        id integer not null auto_increment,        name varchar(255),        primary key (id)    )    create table t_book (        id integer not null auto_increment,        category_id integer,        author varchar(255),        book_name varchar(255),        price double precision,        pubDate datetime,        primary key (id)    )    alter table t_book         add constraint FK_cm584cq6cv5yht4jrqal0ocaq         foreign key (category_id)         references Category (id)

HibernateTest类中的TestSave()方法代码:

/**	 * 保存数据	 */	@Test	public void testSave() {		Session session = HibernateUtil.getSession();		Transaction tx = session.beginTransaction();		Category category = new Category();		category.setName("文学");		Category category1 = new Category();		category1.setName("历史");		Category category2 = new Category();		category2.setName("仙侠");		Category category3 = new Category();		category3.setName("科幻");		Category category4 = new Category();		category4.setName("恐怖");		Book book = new Book();		book.setName("读者");		book.setPrice(5.6);		book.setAuthor("众人");		book.setPubDate(new Date());		book.setCategory(category);		Book book1 = new Book();		book1.setName("傲慢与偏见");		book1.setPrice(80.0);		book1.setAuthor("简.奥斯汀");		book1.setPubDate(new Date());		book1.setCategory(category1);		Book book2 = new Book();		book2.setName("中国历史");		book2.setPrice(30.0);		book2.setAuthor("人民出版社");		book2.setPubDate(new Date());		book2.setCategory(category1);		Book book3 = new Book();		book3.setName("翩眇之旅");		book3.setPrice(70.0);		book3.setAuthor("萧鼎");		book3.setPubDate(new Date());		book3.setCategory(category2);		Book book4 = new Book();		book4.setName("蓝血人");		book4.setPrice(60.0);		book4.setAuthor("卫斯理");		book4.setPubDate(new Date());		book4.setCategory(category3);		Book book5 = new Book();		book5.setName("我的大学");		book5.setPrice(60.5);		book5.setAuthor("高尔基");		book5.setPubDate(new Date());		book5.setCategory(category);		session.save(book);		session.save(book1);		session.save(book2);		session.save(book3);		session.save(book4);		session.save(book5);		session.save(category4);		tx.commit();		HibernateUtil.closeSession();	}

执行保存数据,sql语句如下:

Hibernate:     insert     into        Category        (name)     values        (?)Hibernate:     insert     into        t_book        (category_id, author, book_name, price, pubDate)     values        (?, ?, ?, ?, ?)Hibernate:     insert     into        Category        (name)     values        (?)Hibernate:     insert     into        t_book        (category_id, author, book_name, price, pubDate)     values        (?, ?, ?, ?, ?)Hibernate:     insert     into        t_book        (category_id, author, book_name, price, pubDate)     values        (?, ?, ?, ?, ?)Hibernate:     insert     into        Category        (name)     values        (?)Hibernate:     insert     into        t_book        (category_id, author, book_name, price, pubDate)     values        (?, ?, ?, ?, ?)Hibernate:     insert     into        Category        (name)     values        (?)Hibernate:     insert     into        t_book        (category_id, author, book_name, price, pubDate)     values        (?, ?, ?, ?, ?)Hibernate:     insert     into        t_book        (category_id, author, book_name, price, pubDate)     values        (?, ?, ?, ?, ?)Hibernate:     insert     into        Category        (name)     values        (?)
数据库表中的数据如图:

HibernateTest类中的查询代码如下:

/**	 * 查询图书	 */	@Test	public void testLoadBook() {		Session session = HibernateUtil.getSession();		Transaction tx = session.beginTransaction();		Book book = (Book) session.load(Book.class, 1) ;				System.out.println("-------------------------");		System.out.println("bookName = "+book.getName());		System.out.println("===========================");		System.out.println("categoryName = "+book.getCategory().getName());				tx.commit();		HibernateUtil.closeSession();	}
打印的sql语句如下:

INFO: HHH000232: Schema update complete-------------------------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        t_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=?bookName = 读者===========================categoryName = 文学
从sql语句可以看出,

当执行Book book = (Book) session.load(Book.class, 1) ;这句话时,并没有打印sql语句,

当查询book.getName(),图书的Name时,打印了查询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        t_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=?

这两条sql语句可以看出,先根据book的id
查询了t_book表,t_book表中有category_id,又根据category_id查询了Category表。

当我们把Book.hbm.xml中的lazy改成proxy时,如图:

执行TestLoadBook()方法,打印的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        t_book book0_     where        book0_.id=?bookName = 读者===========================Hibernate:     select        category0_.id as id1_0_0_,        category0_.name as name2_0_0_     from        Category category0_     where        category0_.id=?categoryName = 文学
此时当需要获取对应的数据时,才会执行相应的sql语句。

下面在一的一端设置fetch

Category.hbm.xml代码如下:

fetch设置为select,

testGetCategory()方法的代码如下:

@Test	public void testGetCategory() {		Session session = HibernateUtil.getSession();		Transaction tx = session.beginTransaction();		Category category = (Category) session.get(Category.class, 1);		System.out.println("---------------------------------------------");		System.out.println("category_name=" + category.getName());		System.out.println("============================================");		for (Iterator
iter = category.getBooks().iterator(); iter .hasNext();) { System.out.println(iter.next().getName()); } tx.commit(); HibernateUtil.closeSession(); }

打印的sql语句如下:

Hibernate:     select        category0_.id as id1_0_0_,        category0_.name as name2_0_0_     from        Category category0_     where        category0_.id=?---------------------------------------------category_name=文学============================================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        t_book books0_     where        books0_.category_id=?我的大学读者

从上面可以看出来,get方法,当时就查询了Category表的sql语句,当需要查询Book的数据时,才会执行t_book的数据库表信息。

连接抓取(Join fetching)

先说多段的Book

Book.hbm.xml代码:

fetch是join,lazy是proxy

HIbernateTest类中的testLoadBook()方法,代码:

/**	 * 查询图书	 */	@Test	public void testLoadBook() {		Session session = HibernateUtil.getSession();		Transaction tx = session.beginTransaction();		Book book = (Book) session.load(Book.class, 1);		System.out.println("-------------------------");		System.out.println("bookName = " + book.getName());		System.out.println("===========================");		System.out.println("categoryName = " + book.getCategory().getName());		tx.commit();		HibernateUtil.closeSession();	}

控制台打印的sql语句是:

INFO: HHH000232: Schema update complete-------------------------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        t_book book0_     left outer join        Category category1_             on book0_.category_id=category1_.id     where        book0_.id=?bookName = 读者===========================categoryName = 文学

由上面可以看到,在需要book的信息时,sql语句使用 left outer join 把Category表中的信息也查询了出来。

下面从一的一端Category来查询

HibernateTest类中的testGetCategory()方法代码:

@Test	public void testGetCategory() {		Session session = HibernateUtil.getSession();		Transaction tx = session.beginTransaction();		Category category = (Category) session.get(Category.class, 1);		System.out.println("---------------------------------------------");		System.out.println("category_name=" + category.getName());		System.out.println("============================================");		for (Iterator
iter = category.getBooks().iterator(); iter .hasNext();) { System.out.println(iter.next().getName()); } tx.commit(); HibernateUtil.closeSession(); }

控制台打印的sql语句如下:

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        t_book books1_             on category0_.id=books1_.category_id     where        category0_.id=?---------------------------------------------category_name=文学============================================读者我的大学
从一的一端也是从使用left outer join 方法把t_book表的数据一起查询了出来

接下来我们把Category.hbm.xml和Book.hbm.xml中的lazy和fetch都去掉,执行testLoad()方法,代码如下:

@Test	public void testLoad() {		Session session = HibernateUtil.getSession();		Transaction tx = session.beginTransaction();				List
list = session.createCriteria(Category.class).list() ; System.out.println("---------------------------------"); System.out.println("类型个数:"+list.size()); for (Category category : list) { System.out.println("================================"); System.out.println(category.getName()+"----数据本书:"+category.getBooks().size()); } tx.commit(); HibernateUtil.closeSession(); }

执行后,打印的sql语句如下:

Hibernate:     select        this_.id as id1_0_0_,        this_.name as name2_0_0_     from        Category this_---------------------------------类型个数:5================================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        t_book books0_     where        books0_.category_id=?文学----数据本书:2================================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        t_book books0_     where        books0_.category_id=?历史----数据本书:2================================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        t_book books0_     where        books0_.category_id=?仙侠----数据本书:1================================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        t_book books0_     where        books0_.category_id=?科幻----数据本书:1================================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        t_book books0_     where        books0_.category_id=?恐怖----数据本书:0

子查询(Subselect fetching)

接下来我们在Category.hbm.xml代码中,加入fetch=“subselect” ,如图:

继续testLoad()方法,打印的sql语句如下:

Hibernate:     select        this_.id as id1_0_0_,        this_.name as name2_0_0_     from        Category this_---------------------------------类型个数:5================================Hibernate:     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        t_book books0_     where        books0_.category_id in (            select                this_.id             from                Category this_        )文学----数据本书:2================================历史----数据本书:2================================仙侠----数据本书:1================================科幻----数据本书:1================================恐怖----数据本书:0

由sql语句可以看出,当我们需要查询t_book数据时,sql语句的where语句是:

where        books0_.category_id in (            select                this_.id             from                Category this_        )

一次性将所有的分类Category数据全部查询出来。

假设现在我想查询Category的id是1,3,5的数据,那么方法testLoadWhere代码是:

@Test	public void testLoadWhere() {		Session session = HibernateUtil.getSession();		Transaction tx = session.beginTransaction();				List
list = session.createCriteria(Category.class) .add(Restrictions.in("id", new Integer[]{1,3,5})) .list() ; System.out.println("---------------------------------"); System.out.println("类型个数:"+list.size()); for (Category category : list) { System.out.println("================================"); System.out.println(category.getName()+"----数据本书:"+category.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 (            ?, ?, ?        )---------------------------------类型个数:3================================Hibernate:     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        t_book books0_     where        books0_.category_id in (            select                this_.id             from                Category this_             where                this_.id in (                    ?, ?, ?                )        )文学----数据本书:2================================仙侠----数据本书:1================================恐怖----数据本书:0

批量抓取(Batch fetching

Book.hbm.xml代码修改为:

上面的代码中增加了一个batch-size属性,如图:

你可能感兴趣的文章
javascript设计模式-建立接口的方式(1)
查看>>
javascript设计模式-单体singleton模式(2)
查看>>
javascript设计模式-链式编程(3)
查看>>
大型高并发与高可用缓存架构总结
查看>>
javascript设计模式-工厂模式(4)
查看>>
javascript设计模式-组合模式(6)
查看>>
javascript设计模式-门面模式(7)
查看>>
javascript设计模式-享元模式(10)
查看>>
javascript设计模式-代理模式(11)
查看>>
Executor相关源码分析
查看>>
react之setState解析
查看>>
elasticsearch7.3版本已经不需要额外安装中文分词插件了
查看>>
【重大好消息】elasticsearch 7.3版本已经可以免费使用x-pack就可以设置账号和密码了,让你的数据不再裸奔
查看>>
解决使用logstash中jdbc导入mysql中的数据到elasticsearch中tinyint类型被转成布尔型的问题的方法
查看>>
elasticsearch7.3版本环境搭建(一)elasticsearch安装和配置
查看>>
SEO基本功:站内优化的一些基本手段
查看>>
centos6系列和7系列如何对外开放80,3306端口号或者其他端口号
查看>>
为什么您宁愿吃生活的苦,也不愿吃学习的苦?为什么你不愿意去学习呢
查看>>
解决elasticsearch7.3版本安装过程中遇到的包括内存不够、线程不够等问题
查看>>
日常项目测试用例检查点(来自一线测试人员的吐血总结)
查看>>