我正在使用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...
}
问题是Table1
和Table2
有一些具有相同名称的列,所以我考虑更改查询以返回每列的不同名称,并解析整个ResultSet
但是如果我有很多列或者我只对Table2
进行更改,这将无法很好地扩展(我必须记住不仅要更改Table2
的映射器,而且还要回到这里并制作变化)。
我发现了这个solution,但它看起来过于复杂。
任何想法都会非常感激....
答案 0 :(得分: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());