Java中的ResultSet到对象映射工具:SyncUtil详解
在Java开发中,处理数据库查询结果时,通常需要将ResultSet
中的数据映射到Java对象中。手动处理这个过程不仅繁琐,而且容易出错。为了简化这一过程,我们可以使用一个工具类SyncUtil
来自动完成ResultSet
到对象的映射。本文将详细介绍SyncUtil
的实现和使用方法。
1. SyncUtil的功能概述
SyncUtil
是一个工具类,主要功能是将ResultSet
中的数据自动映射到Java对象中。它支持以下特性:
- 自动类型转换:根据
ResultSet
中的数据类型,自动转换为Java对象的字段类型。 - 字段忽略:可以指定需要忽略的字段,避免不必要的映射。
- 自定义字段映射:支持自定义字段名映射规则,适用于数据库字段名与Java对象字段名不一致的情况。
- 下划线转驼峰:自动将数据库字段名中的下划线转换为Java对象字段名的驼峰命名。
2. SyncUtil的核心实现
2.1 类型映射表
SyncUtil
使用一个Map<Integer, Getter<?>>
来存储SQL类型与对应的ResultSet
获取方法之间的映射关系。例如,Types.VARCHAR
对应ResultSet::getString
,Types.INTEGER
对应ResultSet::getInt
等。
private static final Map<Integer, Getter<?>> getterMap = new HashMap<>();
static {
getterMap.put(Types.VARCHAR, ResultSet::getString);
getterMap.put(Types.CHAR, ResultSet::getString);
getterMap.put(Types.INTEGER, ResultSet::getInt);
getterMap.put(Types.BIGINT, ResultSet::getLong);
// 其他类型映射...
}
2.2 处理ResultSet
handleRow
方法是SyncUtil
的核心方法,它负责将ResultSet
中的数据映射到Java对象中。该方法支持忽略字段和自定义字段映射。
public static <T> List<T> handleRow(ResultSet resultSet, Class<T> clazz, List<String> ignoreFields, Map<String, String> customFieldMapping) throws SQLException {
if (!resultSet.next()) {
return new ArrayList<>();
}
resultSet.previous();
List<T> results = new ArrayList<>();
while (resultSet.next()) {
T instance = clazz.getDeclaredConstructor().newInstance();
ResultSetMetaData metaData = resultSet.getMetaData();
int columnCount = metaData.getColumnCount();
for (int i = 1; i <= columnCount; i++) {
String columnName = metaData.getColumnLabel(i).toLowerCase();
if (!Utility.isNullOrEmpty(ignoreFields) && ignoreFields.contains(columnName)) {
continue;
}
Integer sqlType = metaData.getColumnType(i);
Object value = getValue(resultSet, i, sqlType);
String propertyName = Utility.isNullOrEmpty(customFieldMapping) ? underlineToCamel(columnName) : customFieldMapping.getOrDefault(columnName, underlineToCamel(columnName));
try {
Field field = clazz.getDeclaredField(propertyName);
field.setAccessible(true);
field.set(instance, convertValue(value, field.getType()));
} catch (NoSuchFieldException | IllegalAccessException e) {
System.err.println("Error setting property: " + propertyName + " on class: " + clazz.getName());
e.printStackTrace();
}
}
results.add(instance);
}
return results;
}
2.3 类型转换
convertValue
方法用于将ResultSet
中的值转换为Java对象的字段类型。它支持常见的Java类型,如String
、Integer
、Long
、Double
等。
private static Object convertValue(Object value, Class<?> toType) {
if (value == null) {
return null;
}
if (toType.isInstance(value)) {
return value;
}
try {
if (String.class.equals(toType)) {
return value.toString();
} else if (Integer.class.equals(toType) || int.class.equals(toType)) {
return Integer.parseInt(value.toString().trim());
} else if (Long.class.equals(toType) || long.class.equals(toType)) {
return Long.parseLong(value.toString().trim());
}
// 其他类型处理...
} catch (NumberFormatException e) {
System.err.println("Conversion error for value: " + value + " to type: " + toType);
return null;
}
return value;
}
2.4 下划线转驼峰
underlineToCamel
方法用于将数据库字段名中的下划线转换为Java对象字段名的驼峰命名。
private static String underlineToCamel(String param) {
if (param == null || "".equals(param.trim())) {
return "";
}
int len = param.length();
StringBuilder sb = new StringBuilder(len);
for (int i = 0; i < len; i++) {
char c = param.charAt(i);
if (c == '_') {
if (++i < len) {
sb.append(Character.toUpperCase(param.charAt(i)));
}
} else {
sb.append(c);
}
}
return sb.toString();
}
3. 使用示例
假设我们有一个User
类,其字段与数据库表中的字段对应。我们可以使用SyncUtil
将查询结果映射到User
对象中。
public class User {
private String userName;
private int age;
private Date birthDate;
// getters and setters...
}
// 使用SyncUtil映射ResultSet到User对象
List<User> users = SyncUtil.handleRow(resultSet, User.class, null, null);
4. 总结
SyncUtil
是一个强大的工具类,能够简化ResultSet
到Java对象的映射过程。通过自动类型转换、字段忽略、自定义字段映射等功能,开发者可以更高效地处理数据库查询结果。希望本文的介绍能帮助你在实际项目中更好地使用SyncUtil
。
作者: zhangwqe