不同于 4 个表的 Hibernate 列表
Hibernate list distinct from 4 tables
我们正在将 sql 中的一些遗留代码重写为 gorm with hibernate。
我偶然发现了一个问题——我们有 4 个不同的 table,映射到 4 个域 类。他们每个人都有一个 column/attribute 同名。
考虑以下(实际上很愚蠢)tables 以进行简化:
+-------------------+ +---------------------------+
| id | name | role | | id | position | role |
+-------------------+ +---------------------------+
| 1 | John | admin | | 1 | manager | admin |
| 2 | Bob | user | | 2 | sysadmin | superuser |
+-------------------+ +---------------------------+
从这些 tables/classes 中,我需要提取所有 distinct 角色。
使用 SQL,这可以通过 union:
轻松完成
SELECT role FROM Table1 UNION SELECT role FROM Table2 GROUP BY role
returns 想要的结果:[管理员、用户、超级用户]
现在我想知道,gorm/hibernate 如何做到这一点。一种可能的解决方案是使用以下两个标准:
first = Table1.createCriteria().list {
projections {
distinct "role"
}
}
second = Table2.createCriteria().list {
projections {
distinct "role"
}
}
然后浏览它们并过滤重复项。然而,这不是很有效,并且花费的时间几乎是原始查询的两倍(给定 4 tables,实际上导致 4 个查询)。
那么,对此最有效(时间和资源)的解决方案是什么?
//更新(回应@Emmanuel)
我无法控制数据库。我的访问权限是只读的。更可怕的是,table 中总共有大约 400 万行。这些数据会定期更新,并且每分钟都会添加新行,因此无法在某处创建新的 table。
GORM/Hibernate 不支持 UNION 查询。我的建议是规范化 tables,以便列(例如角色)位于单个 table 中,其他人通过外键引用它。使用您的 table 示例:
+-----------------+
+ id | role +
+-----------------+
+ 1 | admin +
+ 2 | user +
+ 3 | superuser +
+-----------------+
+-------------------+
+ id | name | role +
+-------------------+
+ 1 | John | 1 +
+ 2 | Bob | 2 +
+-------------------+
+---------------------------+
+ id | position | role +
+---------------------------+
+ 1 | manager | 1 +
+ 2 | sysadmin | 3 +
+---------------------------+
然后,当然,您可以简单地查询新域 class。
如果你不想使用 HQL,你可以这样做:
List<Role> list = Table1.createCriteria().list {
projections {
distinct "role"
property "role"
}
}
list = Table2.createCriteria().list {
not{
'in'('role', list)
}
projections {
distinct "role"
property "role"
}
}
我们正在将 sql 中的一些遗留代码重写为 gorm with hibernate。 我偶然发现了一个问题——我们有 4 个不同的 table,映射到 4 个域 类。他们每个人都有一个 column/attribute 同名。 考虑以下(实际上很愚蠢)tables 以进行简化:
+-------------------+ +---------------------------+
| id | name | role | | id | position | role |
+-------------------+ +---------------------------+
| 1 | John | admin | | 1 | manager | admin |
| 2 | Bob | user | | 2 | sysadmin | superuser |
+-------------------+ +---------------------------+
从这些 tables/classes 中,我需要提取所有 distinct 角色。 使用 SQL,这可以通过 union:
轻松完成SELECT role FROM Table1 UNION SELECT role FROM Table2 GROUP BY role
returns 想要的结果:[管理员、用户、超级用户]
现在我想知道,gorm/hibernate 如何做到这一点。一种可能的解决方案是使用以下两个标准:
first = Table1.createCriteria().list {
projections {
distinct "role"
}
}
second = Table2.createCriteria().list {
projections {
distinct "role"
}
}
然后浏览它们并过滤重复项。然而,这不是很有效,并且花费的时间几乎是原始查询的两倍(给定 4 tables,实际上导致 4 个查询)。 那么,对此最有效(时间和资源)的解决方案是什么?
//更新(回应@Emmanuel)
我无法控制数据库。我的访问权限是只读的。更可怕的是,table 中总共有大约 400 万行。这些数据会定期更新,并且每分钟都会添加新行,因此无法在某处创建新的 table。
GORM/Hibernate 不支持 UNION 查询。我的建议是规范化 tables,以便列(例如角色)位于单个 table 中,其他人通过外键引用它。使用您的 table 示例:
+-----------------+
+ id | role +
+-----------------+
+ 1 | admin +
+ 2 | user +
+ 3 | superuser +
+-----------------+
+-------------------+
+ id | name | role +
+-------------------+
+ 1 | John | 1 +
+ 2 | Bob | 2 +
+-------------------+
+---------------------------+
+ id | position | role +
+---------------------------+
+ 1 | manager | 1 +
+ 2 | sysadmin | 3 +
+---------------------------+
然后,当然,您可以简单地查询新域 class。
如果你不想使用 HQL,你可以这样做:
List<Role> list = Table1.createCriteria().list {
projections {
distinct "role"
property "role"
}
}
list = Table2.createCriteria().list {
not{
'in'('role', list)
}
projections {
distinct "role"
property "role"
}
}