如何使用 JDBI 注解 select 将查询结果聚合成元组?
How to select an aggregate query result into tuples using JDBI annotations?
我正在使用 JDBI,我需要 运行 使用聚合函数进行查询。
我将如何读取此查询的结果?我可以使用什么 return 类型来方便?
@SqlQuery("select count(*), location from Customers group by location")
public Type getCustomersCountByLocation();
我可能会为聚合函数结果添加一个别名并编写一个匹配的 POJO
@SqlQuery("select count(*) as customerCount, location from Customers group by location")
public List<CustomerLocation> getCustomersCountByLocation();
POJO 是:
public class CustomerLocation {
private int customerCount;
private String location;
public CustomerLocation(int customerCount, String location) {
this.customerCount = customerCount;
this.location = location;
}
//getters
}
但这似乎有很多不必要的样板文件。我可以为这种查询编写一个通用的对象,但这会引入不必要的耦合。
JDBI 是否支持任何类型的 OOTB,它允许我select 将我的查询结果转换为使用正确类型参数化的任意 n 元组?
伪代码:
@SqlQuery("select count(*) as customerCount, location from Customers group by location")
public List<Tuple<Integer, String>> getCustomersCountByLocation();
您可以改用地图。您只需编写一次映射器,它就可以用于所有聚合查询,也可以用于其他用例。
@SqlQuery("select count(*) as customerCount, location from Customers group by location")
@Mapper(MapMapper.class)
public Map getCustomersCountByLocation();
并像这样定义映射器。
public class MapMapper implements ResultSetMapper<Map<String, Integer>> {
@Override
public Map<String, Integer> map(int index, ResultSet r, StatementContext ctx) throws SQLException {
HashMap<String, Integer> result = new HashMap<>();
for(int i =1; i <= r.getMetaData().getColumnCount(); i++) {
String columnName = r.getMetaData().getColumnName(i);
Integer value = r.getInt(i);
result.put(columnName, value);
}
return result;
}
}
是一个非常好的问题,但我只是想 post 回答具体问题是有人想知道的。
Manikandan 建议的内容可以用 org.apache.commons.lang3.tuple.Pair
完成。
@SqlQuery("select count(*) as customerCount, location from Customers group by location")
@Mapper(CustomerCountByLocationMapper.class)
public List<Pair<String, Integer>> getCustomersCountByLocation();
然后在映射器中class:
public class CustomerCountByLocationMapper implements ResultSetMapper<Pair<String, Integer>> {
@Override
public Pair<String, Integer> map(int index, ResultSet r, StatementContext ctx) throws SQLException {
String location = r.getString("location");
Integer customerCount = r.getInt("customerCount");
return Pair.of(source, count);
}
}
在这种情况下,getCustomersCountByLocation
方法将 return 一个 List<Pair<String,Integer>>
,正如另一个答案所指出的,这是一个愚蠢的类型和一个与此成对的列表某种语义实际上是一张地图。
同时,ResultSetMapper
接口足够灵活,可以映射到完全任意的类型。在更合适的上下文中,Pair
可以与几行代码一起使用。
我正在使用 JDBI,我需要 运行 使用聚合函数进行查询。
我将如何读取此查询的结果?我可以使用什么 return 类型来方便?
@SqlQuery("select count(*), location from Customers group by location")
public Type getCustomersCountByLocation();
我可能会为聚合函数结果添加一个别名并编写一个匹配的 POJO
@SqlQuery("select count(*) as customerCount, location from Customers group by location")
public List<CustomerLocation> getCustomersCountByLocation();
POJO 是:
public class CustomerLocation {
private int customerCount;
private String location;
public CustomerLocation(int customerCount, String location) {
this.customerCount = customerCount;
this.location = location;
}
//getters
}
但这似乎有很多不必要的样板文件。我可以为这种查询编写一个通用的对象,但这会引入不必要的耦合。
JDBI 是否支持任何类型的 OOTB,它允许我select 将我的查询结果转换为使用正确类型参数化的任意 n 元组?
伪代码:
@SqlQuery("select count(*) as customerCount, location from Customers group by location")
public List<Tuple<Integer, String>> getCustomersCountByLocation();
您可以改用地图。您只需编写一次映射器,它就可以用于所有聚合查询,也可以用于其他用例。
@SqlQuery("select count(*) as customerCount, location from Customers group by location")
@Mapper(MapMapper.class)
public Map getCustomersCountByLocation();
并像这样定义映射器。
public class MapMapper implements ResultSetMapper<Map<String, Integer>> {
@Override
public Map<String, Integer> map(int index, ResultSet r, StatementContext ctx) throws SQLException {
HashMap<String, Integer> result = new HashMap<>();
for(int i =1; i <= r.getMetaData().getColumnCount(); i++) {
String columnName = r.getMetaData().getColumnName(i);
Integer value = r.getInt(i);
result.put(columnName, value);
}
return result;
}
}
Manikandan 建议的内容可以用 org.apache.commons.lang3.tuple.Pair
完成。
@SqlQuery("select count(*) as customerCount, location from Customers group by location")
@Mapper(CustomerCountByLocationMapper.class)
public List<Pair<String, Integer>> getCustomersCountByLocation();
然后在映射器中class:
public class CustomerCountByLocationMapper implements ResultSetMapper<Pair<String, Integer>> {
@Override
public Pair<String, Integer> map(int index, ResultSet r, StatementContext ctx) throws SQLException {
String location = r.getString("location");
Integer customerCount = r.getInt("customerCount");
return Pair.of(source, count);
}
}
在这种情况下,getCustomersCountByLocation
方法将 return 一个 List<Pair<String,Integer>>
,正如另一个答案所指出的,这是一个愚蠢的类型和一个与此成对的列表某种语义实际上是一张地图。
同时,ResultSetMapper
接口足够灵活,可以映射到完全任意的类型。在更合适的上下文中,Pair
可以与几行代码一起使用。