Hibernate Union 替代方案
使用 hibernate 实现联合查询有哪些替代方案? 我知道 hibernate 目前不支持联合查询,现在我看到建立联合的唯一方法是使用视图表。
另一种选择是使用纯 jdbc,但这样我就会失去所有示例/条件查询的好处,以及 hibernate 对表/列执行的 hibernate 映射验证。
What alternatives do I have to implement a union query using hibernate? I know hibernate does not support union queries at the moment, right now the only way I see to make a union is to use a view table.
The other option is to use plain jdbc, but this way I would loose all my example/criteria queries goodies, as well as the hibernate mapping validation that hibernate performs against the tables/columns.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
您可以使用
id in (select id from ...) 或 id in (select id from ...)
例如,
您可以
使用 non-working至少使用不过,MySQL,稍后您会遇到性能问题。 有时,对两个查询执行穷人联接会更容易:
执行两个简单查询通常比执行一个复杂查询更好。
编辑:
举个例子,这里是子选择解决方案生成的 MySQL 查询的 EXPLAIN 输出:
最重要的是,1. row 不使用任何索引并考虑 200k+ 行。 坏的! 该查询的执行花费了 0.7 秒,其中两个子查询都以毫秒为单位。
You could use
id in (select id from ...) or id in (select id from ...)
e.g. instead of non-working
you could do
At least using MySQL, you will run into performance problems with it later, though. It's sometimes easier to do a poor man's join on two queries instead:
It's often better to do two simple queries than one complex one.
EDIT:
to give an example, here is the EXPLAIN output of the resulting MySQL query from the subselect solution:
Most importantly, 1. row doesn't use any index and considers 200k+ rows. Bad! Execution of this query took 0.7s wheres both subqueries are in the milliseconds.
使用视图。 相同的类可以使用实体名称映射到不同的表/视图,因此您甚至不会有太多重复。 在那里,做到了这一点,效果很好。
普通 JDBC 还有另一个隐藏的问题:它不知道 Hibernate 会话缓存,因此如果某些内容被缓存到事务结束并且没有从 Hibernate 会话中刷新,则 JDBC 查询将找不到它。 有时可能会非常令人困惑。
Use VIEW. The same classes can be mapped to different tables/views using entity name, so you won't even have much of a duplication. Being there, done that, works OK.
Plain JDBC has another hidden problem: it's unaware of Hibernate session cache, so if something got cached till the end of the transaction and not flushed from Hibernate session, JDBC query won't find it. Could be very puzzling sometimes.
我必须同意弗拉基米尔的观点。 我也研究过在 HQL 中使用 UNION,但找不到解决方法。 奇怪的是,我可以发现(在 Hibernate FAQ 中)UNION 不受支持,与 UNION 相关的错误报告被标记为“已修复”,新闻组的人说这些语句将在 UNION 被截断,而其他新闻组的人报告它有效美好的...
经过一天的研究后,我最终将 HQL 移植回纯 SQL,但在数据库中的视图中执行此操作将是一个不错的选择。 就我而言,部分查询是动态生成的,因此我必须在代码中构建 SQL。
I have to agree with Vladimir. I too looked into using UNION in HQL and couldn't find a way around it. The odd thing was that I could find (in the Hibernate FAQ) that UNION is unsupported, bug reports pertaining to UNION marked 'fixed', newsgroups of people saying that the statements would be truncated at UNION, and other newsgroups of people reporting it works fine...
After a day of mucking with it, I ended up porting my HQL back to plain SQL, but doing it in a View in the database would be a good option. In my case, parts of the query were dynamically generated, so I had to build the SQL in the code instead.
Hibernate 6 添加了对 UNION 的支持。
因此,您现在可以在 JPQL 查询中使用
UNION
,如下所示:如果没有要删除的重复项,您还可以使用
UNION ALL
:除了
UNION< /code>,您还可以使用
EXCEPT
和INTERSECT
。Hibernate 6 added support for UNION.
So, you can now use
UNION
in JPQL queries like this:And you can also also use
UNION ALL
if there are no duplicates to be removed:Besides
UNION
, you can also useEXCEPT
andINTERSECT
.我有一个针对 HQL 中联合的一个关键场景(我为此付出了很多努力)的解决方案。
例如,而不是不工作:-
或者
您可以在 Hibernate HQL 中执行 ->
然后您可以添加两个列表 ->
I have a solution for one critical scenario (for which I struggled a lot )with union in HQL .
e.g. Instead of not working :-
OR
YOU could do in Hibernate HQL ->
then u can add both list ->
视图是一种更好的方法,但由于 hql 通常返回一个 List 或 Set...您可以执行 list_1.addAll(list_2)。 与工会相比完全糟糕,但应该可行。
A view is a better approach but since hql typically returns a List or Set... you can do list_1.addAll(list_2). Totally sucks compared to a union but should work.
也许我有一个更直接的问题需要解决。 我的“例如”是在 JPA 中,Hibernate 作为 JPA 提供者。
我将三个选择(第二种情况是两个)拆分为多个选择,并组合自己返回的集合,有效地替换了“全部联合”。
Perhaps I had a more straight-forward problem to solve. My 'for instance' was in JPA with Hibernate as the JPA provider.
I split the three selects (two in a second case) into multiple select and combined the collections returned myself, effectively replacing a 'union all'.
我也经历过这种痛苦 - 如果查询是动态生成的(例如 Hibernate Criteria),那么我找不到一种实用的方法来做到这一点。
对我来说好消息是,我只是研究联合来解决在 Oracle 数据库中使用“或”时的性能问题。
帕特里克发布的解决方案(使用一组以编程方式组合结果)虽然丑陋(特别是因为我也想进行结果分页)对我来说已经足够了。
I too have been through this pain - if the query is dynamically generated (e.g. Hibernate Criteria) then I couldn't find a practical way to do it.
The good news for me was that I was only investigating union to solve a performance problem when using an 'or' in an Oracle database.
The solution Patrick posted (combining the results programmatically using a set) while ugly (especially since I wanted to do results paging as well) was adequate for me.
这是一个特殊情况,但可能会启发您创建自己的解决方案。 这里的目标是计算两个不同表中记录满足特定条件的记录总数。 我相信这种技术适用于任何需要跨多个表/源聚合数据的情况。
我有一些特殊的中间类设置,因此调用命名查询的代码简短而有趣,但是您可以使用通常与命名查询结合使用的任何方法来执行查询。
正如您在这里所看到的,命名查询开始看起来非常像联合语句:
这里的神奇之处在于创建一个虚拟表并向其中插入一条记录。 就我而言,我将其命名为 Dual1,因为我的数据库是 Oracle,但我认为您如何称呼虚拟表并不重要。
不要忘记插入您的虚拟记录:
Here is a special case, but might inspire you to create your own work around. The goal here is to count the total number of records from two different tables where records meet a particular criteria. I believe this technique will work for any case where you need to aggregate data from across multiple tables/sources.
I have some special intermediate classes setup, so the code which calls the named query is short and sweet, but you can use whatever method you normally use in conjunction with named queries to execute your query.
As you can see here, the named query begins to look an aweful lot like a union statement:
Part of the magic here is to create a dummy table and insert one record into it. In my case, I named it dual1 because my database is Oracle, but I don't think it matters what you call the dummy table.
Don't forget to insert your dummy record:
正如 Patrick 所说,从每个 SELECT 中附加 LIST 是个好主意,但请记住,它的作用类似于 UNION ALL。 为了避免这种副作用,只需控制对象是否已添加到最终集合中即可。 如果没有,则添加它。
您应该关心的其他事情是,如果每个SELECT中有任何JOIN,结果将是对象数组的列表(
List
),因此您必须迭代它以仅保留您需要的对象。希望它有效。
As Patrick said, appending the LISTs from each SELECT would be a good idea but remember that it acts like UNION ALL. To avoid this side effect, just control if the object is already added in final collection or not. If no, then add it.
Something else that you should care about is that if you have any JOIN in each SELECT, the result would be a list of object array(
List<Object[]>
) so you have to iterate over it to only keep the object that you need.Hope it works.