文档章节

如何抓取平行集合

猪刚烈
 猪刚烈
发布于 2014/10/12 11:47
字数 1148
阅读 46
收藏 0

「深度学习福利」大神带你进阶工程师,立即查看>>>

join抓取两个以上的平行集合会产生笛卡尔积,而如果使用subselect抓取又会失去动态抓取集合其他依赖对象的机会。要怎样才能动态地抓取平行集合呢?目前我能想到的一种方法就是生成多条select,分别抓取平行集合。我觉得这并不是一个很完美的方案,但是它却实是可行的。

以Forum为例,在某个use case中我们需要加载一个Forum,同时要显示它的所有Thread以及Moderator.Forum的类代码为:

@Entity
@Table
public class Forum implements ForumNode,Serializable{
    @ManyToMany
    private Set<User> moderators;
	
    @OneToMany
    private List<Thread> threads = new ArrayList<Thread>();
}
 

根据ID加载一个Forum,并将这两个集合抓取出来的方法是:

public Forum getForumWithModeratorsAndThreads(final long forumId){
		return (Forum) getHibernateTemplate().executeWithNativeSession(new HibernateCallback() {			
			public Object doInHibernate(Session session) throws HibernateException,	SQLException {
				//Get forum.
				String getForuumHql= "from Forum as forum where forum.id=:forumId";
				Forum forum = (Forum) session.createQuery(getForuumHql).setParameter("forumId", forumId).uniqueResult();
				//Fetch threads.
				String fetchForumThreadsHql = "from Forum as forum left join fetch forum.threads as thread left join fetch thread.subject where forum=:forum";
				session.createQuery(fetchForumThreadsHql).setParameter("forum", forum).list();
				//Fetch moderators.
				String fetchForumMorderatorsHql = "from Forum as forum left join fetch forum.moderators as moderator left join fetch moderator.roles where forum=:forum";
				session.createQuery(fetchForumMorderatorsHql).setParameter("forum", forum).list();
				logger.info("The Forum (ID="+forumId+") has loaded with moderators and threads");
				return forum;
			}
		});
	}
 

这段代码做了三个操作,生成三条SQL.第一个操作是加载一个不带任何关联对象的Forum。第二个操作是抓取这个Forum的Thread集合。第三个操作是抓取这个Forum的Moderator集合。

下面是测试代码:

@Test @Transactional
	public void testgetForumWithModeratorsAndThreads(){
		Forum forum = forumRepository.getForumWithModeratorsAndThreads(1L);
		System.out.println("****************************************************");
		System.out.println(forum.getModerators().size());
		System.out.println(forum.getThreads().size());
	}

 

测试的输出结果是:

Hibernate:
    /*
from
    Forum as forum
where
    forum.id=:forumId */ select
        forum0_.id as id2_,
        forum0_.creationTime as creation2_2_,
        forum0_.description as descript3_2_,
        forum0_.groupId as groupId2_,
        forum0_.modifiedTime as modified4_2_,
        forum0_.name as name2_
    from
        Forum forum0_
    where
        forum0_.id=?
Hibernate:
    /*
from
    Forum as forum
left join
    fetch forum.threads as thread
left join
    fetch thread.subject
where
    forum=:forum */ select
        forum0_.id as id2_0_,
        threads1_.id as id5_1_,
        post2_.id as id4_2_,
        forum0_.creationTime as creation2_2_0_,
        forum0_.description as descript3_2_0_,
        forum0_.groupId as groupId2_0_,
        forum0_.modifiedTime as modified4_2_0_,
        forum0_.name as name2_0_,
        threads1_.creationTime as creation2_5_1_,
        threads1_.forumId as forumId5_1_,
        threads1_.modifiedTime as modified3_5_1_,
        threads1_1_.subjectId as subjectId6_1_,
        threads1_.forumId as forumId0__,
        threads1_.id as id0__,
        post2_.authorId as authorId4_2_,
        post2_.creationTime as creation2_4_2_,
        post2_.isSubject as isSubject4_2_,
        post2_.messageBody as messageB4_4_2_,
        post2_.modifiedTime as modified5_4_2_,
        post2_.quotedPostId as quotedPo8_4_2_,
        post2_.threadId as threadId4_2_,
        post2_.title as title4_2_
    from
        Forum forum0_
    left outer join
        Thread threads1_
            on forum0_.id=threads1_.forumId
    left outer join
        Thread_Subject threads1_1_
            on threads1_.id=threads1_1_.threadId
    left outer join
        Post post2_
            on threads1_1_.subjectId=post2_.id
    where
        forum0_.id=?
Hibernate:
    /*
from
    Forum as forum
left join
    fetch forum.moderators as moderator
left join
    fetch moderator.roles
where
    forum=:forum */ select
        forum0_.id as id2_0_,
        user2_.id as id0_1_,
        role4_.id as id1_2_,
        forum0_.creationTime as creation2_2_0_,
        forum0_.description as descript3_2_0_,
        forum0_.groupId as groupId2_0_,
        forum0_.modifiedTime as modified4_2_0_,
        forum0_.name as name2_0_,
        user2_.accountNonExpired as accountN2_0_1_,
        user2_.accountNonLocked as accountN3_0_1_,
        user2_.credentialsNonExpired as credenti4_0_1_,
        user2_.email as email0_1_,
        user2_.enabled as enabled0_1_,
        user2_.password as password0_1_,
        user2_.username as username0_1_,
        user2_.version as version0_1_,
        moderators1_.forumId as forumId0__,
        moderators1_.moderatorId as moderato2_0__,
        role4_.description as descript2_1_2_,
        role4_.name as name1_2_,
        roles3_.userId as userId1__,
        roles3_.roleId as roleId1__
    from
        Forum forum0_
    left outer join
        Forum_Moderator moderators1_
            on forum0_.id=moderators1_.forumId
    left outer join
        User user2_
            on moderators1_.moderatorId=user2_.id
    left outer join
        User_Role roles3_
            on user2_.id=roles3_.userId
    left outer join
        Role role4_
            on roles3_.roleId=role4_.id
    where
        forum0_.id=?
INFO - ForumHibernateRepository$1.doInHibernate(38) | The Forum (ID=1) has loaded with moderators and threads
****************************************************
1
2

 

从运行结果来看,getForumWithModeratorsAndThreads方法返回的Forum是一个已经将moderator和thread抓取出来的Forum实例。当我们在测试代码中访问这两个集合时,并没有任何sql打出,说明它们都已经被抓取出来了。

 

我觉得这个方案不好的地方在于抓取两个平行集合的hql有些怪异,它们select的是Forum,但实际上我们并不是要这个Forum,而是要抓取它的集合。因此执行些hql后,我们也没有要得到查询结果的意思。另外,每次查询都要从Forum开始进行join也觉得多做一些事情。 通过验证我发现, 如果直接select这个forum的thread和moderator集合,再访问这个forum的这两个集合时,它还是要去查DB,这说明, 直接select它们不会导致forum的 thread和 moderator集合(应该是hibernate的colletcion wapper)被加载。我想原因是因为hibernate无法确认我们通过select查出的这些元素一定是forum的全部thread集合。hibernate必须重新执行一次以确保全部的集合被加载出来。因此目前来说,也只有这种方式还算可行。我想以后可能会找到更好的解决方法吧。

猪刚烈

猪刚烈

粉丝 22
博文 708
码字总数 110
作品 1
海淀
程序员
私信 提问
加载中
请先登录后再评论。
5分钟 maven3 快速入门指南

前提条件 你首先需要了解如何在电脑上安装软件。如果你不知道如何做到这一点,请询问你办公室,学校里的人,或花钱找人来解释这个给你。 不建议给Maven的服务邮箱来发邮件寻求支持。 安装Mav...

fanl1982
2014/01/23
1.2W
7
Promises/A 和 when() 实现--When.js

When.js 是 cujojs 的轻量级的 Promises/A 和 when() 实现,从 wire.js 的异步核心和 cujojs 的 IOC 容器派生而来。包含很多其他有用的 Promiss 相关概念,例如联合多个 promiss、mapping 和...

匿名
2013/02/15
7.4K
0
网页抓取工具 --pyrailgun

这是一个非常简单易用的抓取工具 怎么使用? 首先你需要创建一个对应站点的规则文件 比如test.json { } 然后在代码里面把它作为一个任务加入到railgun from railgun import RailGun railgun =...

baizhongwei
2013/02/28
7.8K
0
c-string转换工具集合--stringencoders

c-string转换工具集合,比标准实现快2倍以上(如果有的话)。——该项目被Google Chrome使用。 包括以下C字符串转换工具 base64, standard base64, web/url safe, with configurable alphabe...

江斌
2012/11/07
4.8K
1
JSON地理数据编码格式--GeoJSON

GeoJSON 是一个编码各种地理数据结构的格式。一个GeoJSON对象可以代表一个几何,一个特性,或一组特性。GeoJSON 支持以下几何类型: 点,LineString,多边形,多点,MultiLineString,多个多边形,Ge...

匿名
2012/12/22
1.1W
0

没有更多内容

加载失败,请刷新页面

加载更多

C#中const和readonly有什么区别? - What is the difference between const and readonly in C#?

问题: What is the difference between const and readonly in C#? C#中const和readonly什么区别? When would you use one over the other? 您什么时候可以使用另一个? 解决方案: 参考一...

fyin1314
19分钟前
25
0
百度地图SDK新版内测邀请

本文作者:用****9 百度地图开放平台为开发者提供七大基础服务能力,其中地图SDK和导航SDK是开发者广泛使用的重要基础服务,为了满足开发者更多使用需求以及提升开发者集成后的应用效果,本次...

百度开发者中心
前天
0
0
获取JavaScript数组中的所有唯一值(删除重复项) - Get all unique values in a JavaScript array (remove duplicates)

问题: I have an array of numbers that I need to make sure are unique. 我需要确定一个唯一的数字数组。 I found the code snippet below on the internet and it works great until th......

javail
今天
11
0
如何检查字符串是否为空? - How to check if the string is empty?

问题: Does Python have something like an empty string variable where you can do: Python是否有类似空字符串变量的内容可以在其中执行: if myString == string.empty: Regardless, wh......

富含淀粉
今天
19
0
您如何存储未跟踪的文件? - How do you stash an untracked file?

问题: I have changes to a file, plus a new file, and would like to use git stash to put them away while I switch to another task. 我对一个文件进行了更改,再加上一个新文件,并希......

技术盛宴
今天
39
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部