JdbcTemplate實體映射
阿新 • • 發佈:2019-03-28
ada copy pro 屬性。 限制 tolower bstr poj names
JdbcTemplate實體映射
如果你需要使用JdbcTemplate將查詢的數據映射成Java POJO,那麽這篇文章適合你。
一個例子入門
下面是一個將表中一行記錄映射成Map的例子,也是JdbcTemplate默認提供的功能。
List<Map<String, Object>> result = jdbcTemplate.queryForList("select id, name, age from tbl");
然而,我們更希望得到的是下面這樣的。
List<User> result = jdbcTemplate.queryForList("select id, name, age from tbl", User.class);
其中User中的屬性與字段一一對應,還能自動將下劃線轉成駝峰。
開始
實現思路是通過反射將字段映射到對象對應的屬性。
核心代碼
public <T> List<T> queryForList(String sql, Class<T> clazz, Object... params) { final List<T> result = new ArrayList<>(); jdbcTemplate.query(sql, params, rs -> { try { // 字段名稱 List<String> columnNames = new ArrayList<>(); ResultSetMetaData meta = rs.getMetaData(); int num = meta.getColumnCount(); for (int i = 0; i < num; i++) { columnNames.add(meta.getColumnLabel(i + 1)); } // 設置值 do { T obj = clazz.getConstructor().newInstance(); for (int i = 0; i < num; i++) { // 獲取值 Object value = rs.getObject(i + 1); // table.column形式的字段去掉前綴table. String columnName = resolveColumn(columnNames.get(i)); // 下劃線轉駝峰 String property = CamelCaseUtils.toCamelCase(columnName); // 復制值到屬性,這是spring的工具類 BeanUtils.copyProperty(obj, property, value); } result.add(obj); } while (rs.next()); } catch (Exception e) { throw new QueryException(e); } }); if (CollectionUtils.isEmpty(result)) { return Collections.emptyList(); } return result; }
註意:
String columnName = resolveColumn(columnNames.get(i))
用來去掉字段的表前綴,比如t.id
替換成id
String property = CamelCaseUtils.toCamelCase(columnName)
用來將字段的下劃線轉成屬性的駝峰形式,比如page_view
轉換成pageView
BeanUtils.copyProperty(obj, property, value)
是用來復制值到對象的屬性中,BeanUtils
是spring的工具類,經常會使用到
下面是兩個工具方法或類。
去掉表前綴
之所以去掉表前綴,是為了避免在SQL中使用別名,導致SQL過長。
private String resolveColumn(String column) {
final int notExistIndex = -1;
int index = column.indexOf(".");
if (index == notExistIndex) {
return column;
}
return column.substring(index + 1);
}
字段下劃線轉成屬性的駝峰
當然,下劃線轉駝峰有很多更好的實現,這裏不限制。如下是一個實現:
public final class CamelCaseUtils {
private static final char SEPARATOR = '_';
private CamelCaseUtils() {
}
public static String toCamelCase(String input) {
if (input == null) {
return null;
}
input = input.toLowerCase();
int length = input.length();
StringBuilder sb = new StringBuilder(length);
boolean upperCase = false;
for (int i = 0; i < length; i++) {
char c = input.charAt(i);
if (c == SEPARATOR) {
upperCase = true;
} else if (upperCase) {
sb.append(Character.toUpperCase(c));
upperCase = false;
} else {
sb.append(c);
}
}
return sb.toString();
}
}
使用
接下來就可以愉快的映射成POJO了:
List<User> result = queryForList("select t.id, t.name, t.age, t.mobile_phone from tbl t where t.id < ?", User.class, 100L);
如果參數比較多,還是通過數組傳入:
List<User> result = queryForList("select t.id, t.name, t.age, t.mobile_phone from tbl t where t.id < ?", User.class, new Object[]{100L});
下面定義POJO:
public class User implements Serializabl {
private Long id;
private String name;
private Integer age;
private String mobilePhone;
// 省略到getters、setters
}
補充
映射成一個值
在count時,我們是希望返回一個值的,接下來是將結果映射成一個值。
public <T> T queryOneColumn(String sql, Class<T> clazz, Object... params) {
T result;
if (ArrayUtils.isEmpty(params)) {
result = jdbcTemplate.queryForObject(sql, clazz);
} else {
result = jdbcTemplate.queryForObject(sql, params, clazz);
}
return result;
}
使用:
long total = queryOneColumn("select count(1) from tbl", Long.class);
JdbcTemplate實體映射