java - 按表从 ResultSet 中删除列

标签 java jdbc jdbi

我正在使用 JDBI 查询我们的数据库。我有两个通过外键连接的表,我的查询返回两个表的联接。为了将返回的值转换为对象,我为我的对象实现了 ResultSetMapper。查询中的 ResultSet 包含两个表的列:t1.id、t1.name、t2.id、t2.name。如何根据表名进行拆分?我正在寻找这段代码:

public class T1Object {
    private long id;
    private String name;
    private T2Object t2Object;
}

public class T2Object {
    private long id;
    private String name;
}

public void map(ResultSet r) {
    String t1Name = "Table1 name";
    String t2Name = "Table2 name";

    t1ResultSet = getResultSetByTableName(r, t1Name); // looking for this function's implementation
    t2ResultSet = getResultSetByTableName(r, t2Name);

    // convert each result set to an object using it's mapper...
}

The problem is that Table1 and Table2 have some columns with the same name so I've considered changing the query to return different names for each column and just parse the entire ResultSet but this won't scale well if I have lots of columns or I make changes only to Table2 (I'll have to remember not only change the mapper for Table2 but also go back to here and make changes).

我找到了这个solution但看起来过于复杂。

任何想法将不胜感激......

最佳答案

我建议使用列名前缀作为可选构造函数参数来实现映射器:

class T1Mapper implements ResultSetMapper<T1Object> {
  public T1Mapper() { this(""); }
  public T1Mapper(String prefix) {
    this.prefix = prefix;
  }

  private final String prefix;

  T1Object map(int i, ResultSet rs, StatementContext ctx) throws SQLException {
    return new T1Object(rs.getInt(prefix + "id"),
                        rs.getString(prefix + "name"));
  }
}

// ditto for t2 mapper

因此,当您遇到需要联接具有共同列名的多个表的情况时,请在查询中标记每一列以消除它们的歧义:

List<T1Object> handle.createQuery("select t1.id t1_id, t1.name t1_name, " +
                   "t2.id t2_id, t2.name t2_name " +
                   "from table1 t1 left join table2 t2 " +
                   "on t1.id = t2.t1_id")
      .map(new ResultSetMapper<T1Object>() {
        T1Mapper t1Mapper = new T1Mapper("t1_");
        T2Mapper t2Mapper = new T2Mapper("t2_");

        public T1Object map(int i, ResultSet rs, StatementContext ctx) {
          T1Object t1 = t1Mapper.map(i, rs, ctx);
          T2Object t2 = t2Mapper.map(i, rs, ctx);
          t1.setT2Object(t2);
          return t1;
        }
      })
      .list();

除非有一些我没有听说过的奇特技巧,否则确实无法避免必须为列名添加前缀——除非您想手动编写自定义连接行映射器。

我认为我们在 v3 中更好地解决了这个用例(仍处于 alpha 版本)。所有像 BeanMapper 这样的反射映射器现在都支持列名前缀,如上所述,开箱即用。我们还添加了JoinRowMapper,这使得这个愚蠢的事情变得简单:

@SqlQuery("select t1.id t1_id, t1.name t1_name, " +
          "t2.id t2_id, t2.name t2_name " +
          "from table1 t1 left join table2 t2 " +
          "on t1.id = t2.t1_id")
@RegisterBeanMapper(value = {T1Object.class, T2Object.class},
                    prefix = {"t1_", "t2_"})
@RegisterJoinRowMapper({T1Object.class, T2Object.class})
List<JoinRow> listJoins();

因此:

myDao.listJoins()
     .stream()
     .map(joinRow -> {
       T1Object t1 = joinRow.get(T1Object.class);
       T2Object t2 = joinRow.get(T2Object.class);

       // merge the individual entities in your join rows however you like
       t1.setT2(t2);
       return t1;
     })
     .collect(toList());

关于java - 按表从 ResultSet 中删除列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39779983/

相关文章:

java - 如何多次运行相同的代码来创建用户

java - Selenium 网络驱动程序 : is it a professional practice to use xpath?

java - 准备好的语句和SQL注入(inject)

java - 数组中的多种类型用于初始化

java - Spring Boot 过滤器未返回正确的响应

java - 多个 Teradata DDL 查询加上使用 Java 的选择

Java JDBC 在表中插入数据后获取字符串主键值

java - JDBI 结果集映射器从查询结果集中创建对象列表?

java - 如何在 JDBI sql api 中打印 @SqlQuery 注释

java - JDBI3动态创建WHERE子句