作者adrianshum (Alien)
看板java
标题Re: [问题] 请问JPA如何做阶层式查询
时间Sat Jul 19 11:44:58 2014
类似的情况在实务上有遇过很多次。也用过不少方法去解决,
现简单罗列出来,希望能给大家一点方向去决定合用的情况。
首先从persistence 层面出发,实际用过的方法有两种:
A) 最直觉的方法:每个 node 存 parent 的 ID (就是之前文
章用的方法)
B) 每个 node 存的是 "左右" 两数值, 类似:
http://www.sitepoint.com/hierarchical-data-database-2/
A) 最能对应 OOP,本身的资料就是差不多直接对映 hiererchy 的结构
e.g.
class Node {
Node parent;
List<Node> children;
}
实际转换成 object 来操作的话,A 会比较容易和直觉
B) 对於一般的 DB (何谓非一般後面再解释)来说,能轻易就
能用 SQL 取得某node 底下的 subtree, 或某 node 的 parents,
单纯用 SQL 作 insert/delete 等也蛮简单。但转换成 object 操作
的话就不太能直接做到 (至少不能简单利用 ORM 的内置 insert/update
功能)
-----------------------------------------------------------------------
虽然 A 方法对映成 object 很直觉,但还是有一个大问题(就是原问
者提到的): 假设要找某 node 的 subtree 或 parents,不容易直接一句
query 就做到
解决方案有以下:
1) 依靠实际 object 的 navigation,找出你的要 node,然後要找
subtree 或 parents 就轻易很多了。
要做到这效果,方法有以下:
i) 单纯从 DB retrieve 该 node, 然後依靠各 JPA 实作提供的 lazy
fetching, 当你 navigate 某 node 的 parent / children,当时才
自动去 DB 取得。
这是我唯一一个不会建议的方法(我也没有实际做过),因为会不必要
地大量 acess DB (有多少个 node 就会跑多少句 SQL)。
ii) 把整棵 tree structure 一次读入,然後在 memory 建立整个 tree structure。
一般来说,现在的 DBMS 和网路,跑一句简单但结果行数大的 QUERY,
比跑一句复杂但结果量比较小的QUERY,前者会有效率得多 (除非真的
是上十万或百万行),只要留心一下 JDBC 的 FETCH SIZE 就好了。
2) Query 取得相关的资料。
在 B) 里面不是说 A) 的结构不宜 query 吗?对的,不过现在不少 DBMS 都
有提供 hierarchical query 的功能,比如 oracle:
http://docs.oracle.com/cd/B19306_01/server.102/b14200/queries003.htm
靠这种做法,可以有单纯的 DB schema,也可以一句 query 就找到你想要的
subtree etc.
最大的问题是这类 query 是厂商特有的语法,你不可能用 JPQL 或 HQL 之类
写出来。要是写 native query 不是大问题的话,这方法也可以考虑。
找到需要的 subtree, 再结合 object navigation,就可以很有效地做到需
要的功能。
个人的建议是
A1i > A2 > B > A1ii
A1i 做起来单纯,需要的特别知识也少,只要你的 tree strucuture 不是
超巨大(数万 node 以上),一句 query 拿回来然後让 JPA 帮你建构整
个 tree structure 是最直接又简单的做法
B 则是当你的设计主要依靠 SQL 会比较有用 (你的情况看来并非如此)
一点经验分享,希望有用
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 223.19.42.87
※ 文章网址: http://webptt.com/cn.aspx?n=bbs/java/M.1405741506.A.16C.html
※ 编辑: adrianshum (223.19.42.87), 07/19/2014 11:45:57
※ 编辑: adrianshum (223.19.42.87), 07/19/2014 11:47:09
1F:推 NullLife:耶,谢谢分享~ 07/20 00:55