如何使用 Jdbc 模板映射一对多

我遇到了弗拉德在推特上提到的一个堆栈溢出问题。 如何在春季 jdbc 模板中映射一对多关系。

第一个问题是,使用 RowMapper 接口实际上只能映射一对一的关系,因为它假定一个 ResultSet 行将映射到一个对象。

正如RowMapper接口所述:

用于在每行的基础上映射结果集的行... 此接口执行将每行映射到结果对象的实际工作

为了能够映射通常使用联接恢复的一对多,您需要能够将多行聚合到一个对象中。ResultSetExtractor将允许跨 Merge 工作,然后返回一个集合。ResultSet

对于结果集处理,RowMapper 通常是一个更简单的选择,它每行映射一个结果对象,而不是整个结果集映射一个结果对象。

您可以使用根对象 ID 更改来检测新对象何时启动。 代码看起来像。

   List<User> users = new ArrayList<>();
   User currentUser = null;
   while(rs.next()) {
        long id = rs.getLong("id");
        if (currentUser == null) { // initial object
            currentUser = mapUser(rs);
        } else if (currentUser.getId() != id) { // break
            users.add(currentUser);
            currentUser = mapUser(rs);
        }
        currentUser.addRole(mapRole(rs));
   }
   if (currentUser != null) { // last object
        users.add(currentUser);        
   }

这还不错,但随着您添加更多联接,复杂性会迅速增加。

幸运的是,SimpleFlatMapper已经解决了这个问题。 您需要做的就是使用JdbcTemplateMapperFactory 创建 aage。ResultSetExtractor

    private final ResultSetExtractor<List<User>> resultSetExtractor = 
        JdbcTemplateMapperFactory
            .newInstance()
            .addKeys("id") // the column name you expect the user id to be on
            .newResultSetExtractor(User.class);

您现在可以使用它来映射您的一对多。resultSetExtractor

   String query = 
        "SELECT u.id as id, u.username, u.id    as adverts_id, ad.text as adverts_text"
        + "FROM user u LEFT OUTER JOIN advert ad ON ad.account_id = ac.id order by id " 

    List<User> results = template.query(query, resultSetExtractor);

请注意,sfm 使用根 id 中断作为其聚合的基础,因此查询的顺序很重要。

6.2.0以来的更新是一个新选项允许使用无序结果集进行联接映射。unorderedJoin()

如果要将角色列表保留在用户对象之外,该怎么办?

无需使用User类和UserWithRole类,您只需将查询映射到ausing sfm元组或jOOL。Tuple2<User, List<Role>>

    private final ResultSetExtractor<Tuple2<User, List<Role>>> resultSetExtractor = 
        JdbcTemplateMapperFactory
            .newInstance()
            .addKeys("id") // the column name you expect the user id to be on
            .newResultSetExtractor(new TypeReference<Tuple2<User, List<Role>>> {});

然后

   String query = 
        "SELECT u.id as id, u.username, u.id    as adverts_id, ad.text as adverts_text"
        + "FROM user u LEFT OUTER JOIN advert ad ON ad.account_id = ac.id order by id " 

    List<Tuple2<User, List<Role>>> results = template.query(query, resultSetExtractor);

每个元组 2 都有用户及其关联的角色。

总结

您不需要使用复杂的 ORM 将 sql 查询映射到对象,即使有多个一对多关系也是如此。 SimpleFlatMapper已经为您处理了所有的复杂性,因此请放弃编写手动RowMapper,并花时间编写业务逻辑而不是样板映射代码。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值