通过表删除结果集中的列

问题描述:

我正在使用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... 
} 

的问题是,Table1Table2有一些列具有相同的名称,所以我已经考虑更改查询,为每列返回不同的名字,只是解析整个ResultSet但是如果我有很多列,或者我只对Table2进行更改(我将不得不记住更改映射器Table2,但也要返回到此处并进行更改),但这不会很好地扩展。

我发现这个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());