一尘不染

处理巨大数据表时应如何使用Hibernate Mapping

hibernate

问题定义:
我有一个包含大量数据(超过100,000行)的数据库表,表结构像

AppID  DocID  DocStatus 
1      100    0
1      101    1    
2      200    0    
2      300    1

每个applicationID可能有成千上万的文档,我必须获取按applicationID分组的状态为0的文档数和状态为1的文档数。

当我使用hibernate方式映射该对象时,由于大量的表数据,它将占用大量的堆内存。

如何使用Hibernate查询实现这一目标? 还是我应该为此使用SQL查询或存储过程?

注意: 我的Web应用程序在JAVA / Tapestry框架中并使用Hibernate3。数据库是SQL Server 2012。


阅读 164

收藏
2020-06-20

共1个答案

一尘不染

每当遇到以数据为中心的问题(与以Java域模型为中心的问题相对)时,都应直接使用SQL。您的数据库将比Java代码快得多,因为可以对数据进行紧密的计算,而不必通过导线将其全部传输到内存中。另请参阅本博客文章“
2.处理内存中的数据”

您可以直接使用JDBC,本地查询或您选择的任何第三方SQL库(例如MyBatisjOOQ)来实现

您可以使用以下任一查询轻松解决您的问题:

使用GROUP BY

SELECT [AppID], [DocStatus], count(*)
FROM [MyTable]
GROUP BY [AppID], [DocStatus]

SQLFiddle上的示例

使用嵌套选择

SELECT [AppID],
       (SELECT count(*) FROM [MyTable] [t2]
        WHERE [t1].[AppID] = [t2].[AppID]
        AND [DocStatus] = 0) [Status_0],
       (SELECT count(*) FROM [MyTable] [t2]
        WHERE [t1].[AppID] = [t2].[AppID]
        AND [DocStatus] = 1) [Status_1]
FROM [MyTable] [t1]
GROUP BY [AppID]

SQLFiddle上的示例

使用SUM()

SELECT [AppID],
       SUM(IIF([DocStatus] = 0, 1, 0)) [Status_0],
       SUM(IIF([DocStatus] = 1, 1, 0)) [Status_1]
FROM [MyTable] [t1]
GROUP BY [AppID]

SQLFiddle上的示例

使用PIVOT

SELECT [AppID], [0], [1]
FROM (
  SELECT [AppID], [DocStatus]
  FROM [MyTable]
) [t]
PIVOT (count([DocStatus]) FOR [DocStatus] IN ([0], [1])) [pvt]

SQLFiddle上的示例

2020-06-20