2016-09-29 42 views
1

我正在使用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,但它看起來過於複雜。

任何想法將是非常讚賞....

回答

0

我建議有列名的前綴作爲可選的構造函數參數實現的映射器:

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());