我是否加入、循环查询或其他从 SQLiteDatabase 检索嵌套表的东西?
Do I join, loop the queries, or something else to retrieve nested tables from SQLiteDatabase?
如果我有一个深层嵌套 table(5 层)关系,检索相关数据以便我可以将它们存储在我的 Java 对象中的好方法是什么?
这是 table 的样子:
___________ ___________ ___________ ___________ ___________
| Table A | | Table B | | Table C | | Table D | | Table E |
|___________| |___________| |___________| |___________| |___________|
| tableA_id | | tableB_id | | tableC_id | | tableD_id | | tableE_id |
| some_data | | some_data | | some_data | | some_data | | some_data |
|___________| | tableA_id | | tableB_id | | tableC_id | | tableD_id |
|___________| |___________| |___________| |___________|
方法 1 是我目前使用的
- 从基础 table 检索行的查询。我将其存储在 ObjectA.
中
- 从第二个 table 中检索与上一个查询的 ID 匹配的所有行的查询。我将它们存储在 List<ObjectB> inside ObjectA.
- 对于每个 ObjectB,查询检索与 ObjectB 的 ID 匹配的第三个 table 的所有行。我将这些存储在 List<ObjectC> inside ObjectB.
- 对于每个 ObjectC,查询以检索与 ObjectC 的 ID 匹配的第四个 table 的所有行。我将它们存储在 List<ObjectD>inside ObjectC.
- 对于每个 ObjectD,查询以检索与 ObjectD 的 ID 匹配的第五个 table 的所有行。我将它们存储在 List<ObjectE>inside ObjectD.
- 上述所有查询都位于 "db.beginTransaction" 和 "db.endTransaction" 语句中,因此如果一个查询异常失败(错误),则不会创建 ObjectA。
上面的方法有很多循环,也有很多查询。我觉得这不是可行的方法,因为我在循环的每次迭代中不断地从数据库发送和接收数据。
方法 2
我想到的另一种方法是将 5 个 table 连接在一起。这只会导致一个查询,但循环仍然存在,因为我需要对每一层的外部 ID 进行分组和循环。至少通过这种方式,我可以预先获得所有信息。但是,一旦我将数据集中在一起,我就不知道如何将它们分解成各自的对象。这是我的加入的样子:
SELECT * FROM (((tableA
JOIN tableB ON tableA._id = tableB.tableA_id)
JOIN tableC ON tableB._id = tableC.tableB_id)
JOIN tableD ON tableC._id = tableD.tableC_id)
JOIN tableE ON tableD._id = tableE.tableD_id
现在我将如何通过游标来剖析连接并将它们各自的数据放入正确的对象中?
经过一番思考,解决方案有两个:
将服务性能决策传递给用户:
为避免 运行 出现持续的性能问题,为用户提供从服务器 "checkout" objectA 的能力。然后,用户将能够在离线时 veiw/modify objectA。显然前期性能成本是巨大的,但因为它不是默认行为,所以不是问题。
为了避免N+1选择问题,避免网络上不必要的数据传输:
每个嵌套的 table 将像这样存储根 table 参考键:
___________ ___________ ___________ ___________ ___________
| Table A | | Table B | | Table C | | Table D | | Table E |
|___________| |___________| |___________| |___________| |___________|
| tableA_id | | tableB_id | | tableC_id | | tableD_id | | tableE_id |
| some_data | | some_data | | some_data | | some_data | | some_data |
| | | tableA_id | | tableB_id | | tableC_id | | tableD_id |
|___________| | tableA_id | | tableA_id | | tableA_id | | tableA_id |
|___________| |___________| |___________| |___________|
当需要查询ObjectA的数据时,逆序查询如下:
1. SELECT * FROM tableE WHERE tableA_id=?
2. Store the result in MAP<long, List>
3. Each unique entry of TablD_id are stored in a list, mapped by the unique id.
对每个 table 重复上述过程,最后一个 tableB。在这种情况下,总共有 5 个查询而不是 N+1。
然后,应用程序将遍历 MAP 以完整还原对象 A。
如果我有一个深层嵌套 table(5 层)关系,检索相关数据以便我可以将它们存储在我的 Java 对象中的好方法是什么?
这是 table 的样子:
___________ ___________ ___________ ___________ ___________
| Table A | | Table B | | Table C | | Table D | | Table E |
|___________| |___________| |___________| |___________| |___________|
| tableA_id | | tableB_id | | tableC_id | | tableD_id | | tableE_id |
| some_data | | some_data | | some_data | | some_data | | some_data |
|___________| | tableA_id | | tableB_id | | tableC_id | | tableD_id |
|___________| |___________| |___________| |___________|
方法 1 是我目前使用的
- 从基础 table 检索行的查询。我将其存储在 ObjectA. 中
- 从第二个 table 中检索与上一个查询的 ID 匹配的所有行的查询。我将它们存储在 List<ObjectB> inside ObjectA.
- 对于每个 ObjectB,查询检索与 ObjectB 的 ID 匹配的第三个 table 的所有行。我将这些存储在 List<ObjectC> inside ObjectB.
- 对于每个 ObjectC,查询以检索与 ObjectC 的 ID 匹配的第四个 table 的所有行。我将它们存储在 List<ObjectD>inside ObjectC.
- 对于每个 ObjectD,查询以检索与 ObjectD 的 ID 匹配的第五个 table 的所有行。我将它们存储在 List<ObjectE>inside ObjectD.
- 上述所有查询都位于 "db.beginTransaction" 和 "db.endTransaction" 语句中,因此如果一个查询异常失败(错误),则不会创建 ObjectA。
上面的方法有很多循环,也有很多查询。我觉得这不是可行的方法,因为我在循环的每次迭代中不断地从数据库发送和接收数据。
方法 2
我想到的另一种方法是将 5 个 table 连接在一起。这只会导致一个查询,但循环仍然存在,因为我需要对每一层的外部 ID 进行分组和循环。至少通过这种方式,我可以预先获得所有信息。但是,一旦我将数据集中在一起,我就不知道如何将它们分解成各自的对象。这是我的加入的样子:
SELECT * FROM (((tableA
JOIN tableB ON tableA._id = tableB.tableA_id)
JOIN tableC ON tableB._id = tableC.tableB_id)
JOIN tableD ON tableC._id = tableD.tableC_id)
JOIN tableE ON tableD._id = tableE.tableD_id
现在我将如何通过游标来剖析连接并将它们各自的数据放入正确的对象中?
经过一番思考,解决方案有两个:
将服务性能决策传递给用户:
为避免 运行 出现持续的性能问题,为用户提供从服务器 "checkout" objectA 的能力。然后,用户将能够在离线时 veiw/modify objectA。显然前期性能成本是巨大的,但因为它不是默认行为,所以不是问题。
为了避免N+1选择问题,避免网络上不必要的数据传输:
每个嵌套的 table 将像这样存储根 table 参考键:
___________ ___________ ___________ ___________ ___________
| Table A | | Table B | | Table C | | Table D | | Table E |
|___________| |___________| |___________| |___________| |___________|
| tableA_id | | tableB_id | | tableC_id | | tableD_id | | tableE_id |
| some_data | | some_data | | some_data | | some_data | | some_data |
| | | tableA_id | | tableB_id | | tableC_id | | tableD_id |
|___________| | tableA_id | | tableA_id | | tableA_id | | tableA_id |
|___________| |___________| |___________| |___________|
当需要查询ObjectA的数据时,逆序查询如下:
1. SELECT * FROM tableE WHERE tableA_id=?
2. Store the result in MAP<long, List>
3. Each unique entry of TablD_id are stored in a list, mapped by the unique id.
对每个 table 重复上述过程,最后一个 tableB。在这种情况下,总共有 5 个查询而不是 N+1。
然后,应用程序将遍历 MAP 以完整还原对象 A。