使用 RowMapper 返回 Map<String,Map<String,List<Object>>>

Posted

技术标签:

【中文标题】使用 RowMapper 返回 Map<String,Map<String,List<Object>>>【英文标题】:Using RowMapper to return Map<String,Map<String,List<Object>>> 【发布时间】:2017-02-03 14:25:40 【问题描述】:

我的数据库中的每一行都是这样的

School  Class   StudentID   Name    Age
123      8        811       John    10
123      8        812       Smith   11
123      8        821       John    12
123      8        822       Smith   13
123      9        911       John    14
123      9        912       Smith   15
456      8        811       John    10
456      8        812       Smith   11

现在我想像这样返回上面的数据

Map<String,Map<String,List<Object>>>

ie. Map<School,Map<Class,List<StudentID>>>

我正在使用 Spring 的 JdbcTemplateRowMapper,但我能得到的只是所有行的列表。因为我无法在我的 RowMapper 中维护我的主地图(我可以在 RowMapper 类中有一个静态地图吗??但我不希望它是静态的,因为这是一个网络服务,后续调用可能会搞砸。 ),我只能选择获取此行列表,然后使用我的逻辑创建我想要的集合。

我开始了解ResultSetExtractor,但我找不到如何使用它来完成这项工作。

请让我知道是否有任何方法可以使用行映射器或某种方式完成此操作。或者我解决这个问题的唯一方法是我必须再次迭代列表并得到我想要的。

编辑: 我的查询是这样的选择查询:

SELECT * from TABLENAME

实际上从 Java 中检索 ResultSet 需要 40 分钟。

由于 DB 调用用于填充缓存对象,它每 4 小时使用 CRON 完成一次,我不介意 40 分钟的时间延迟,因为实际的 REST 调用将引用缓存对象。但我仍然想尽可能高效地做到这一点。

如果还有其他方法可以处理这种情况,请告诉我。每个 REST 调用的正常 jdbc 调用代价高昂,因为我们每秒会收到 100 个请求。

【问题讨论】:

我假设您的每个实体都有一个 DAO 类?为什么不让你的 DAO 将 List 转换为 Map 并将其返回给外界? jdbcTemplate 调用在 DAO 内部,我想知道这是否可以使用 RowMapper 完成。 所以您基本上希望JdbcTemplate 在您使用它执行查询时为您形成Map?我相信您实施的任何解决方案最终都会在内部将List 转换为Map,那么为什么不让您的DAO 去做呢? 是的,这正是我想要的。但是有没有办法做到这一点,或者我应该从从 jdbcTemplate 获得的列表中自己做到这一点 我想应该有办法做到这一点。但问题是你这样做的动机是什么? 【参考方案1】:

行映射器

您可以实现一个状态完整的RowMapper 来解决您的问题,但它与RowMapper 的想法并不完全一致,RowMapper 被认为是无状态且可重用的,如 JavaDoc 中所述:

... RowMapper 对象通常是无状态的,因此可重用...

RowMapper用于行到对象的转换,这意味着ResultSet的每一行都得到一个自己的Object

结果集提取器

真正适合您任务的是ResultSetExtractorResultSetExtractor 是为 ResultSet 到 Object 的转换而设计的。

只需通过迭代 ResultSet 来实现填充 Map 并将 ResultSetExtractor 实现的实例传递给您的 JdbcTemplate.query(...) 调用。


2017 年 2 月 9 日更新

在评论说使用ResultSetExtractor 的示例很有用时,我偶然发现了RowCallbackHandler 接口。虽然这两个选项都允许您实现所需的行为,但 RowCallbackHandler 会为您处理 ResultSet 迭代。也可以通过JdbcTemplate.query(...)调用使用。

对于RowCallbackHandlerResultSetExtractor 的示例,我推荐以下文章Ram Satish:http://www.javarticles.com//2015/02/example-of-spring-callbacks-used-in-jdbctemplate.html

【讨论】:

谢谢。但是在我执行 jdbc 调用之后立即构建我的实际地图是否有效? (性能方面。)我正在使用的 SELECT * from TABLE 查询实际上需要 40 分钟才能完成。如果我想再次构建地图,我将不得不再次迭代 ResultSet。这就是为什么认为这种方法有助于提高性能的原因。 我今天尝试了 ResultSetExtractor 并且能够做我想做的事情。您能否添加一个关于 ResultSetExtractor 工作原理的小实现 sn-p,以便答案对其他人更有用?

以上是关于使用 RowMapper 返回 Map<String,Map<String,List<Object>>>的主要内容,如果未能解决你的问题,请参考以下文章

Spring利用spring的JdbcTemplate查询返回结果映射到自定义类型

用于 RowMapper 的 Spring jdbc 模板的单元测试用例

spring 中的 RowMapper

RowMapper问题

spring对JDBC整合的时候,要注意自己写一个映射,继承RowMapper,查询的时候会用到,将返回的ResultSet一条对应一个Employee对象。

Spring使用RowMapper将数据中的每一行封装成用户定义的类