工作中有时候不得不使用JDBC进行查询,此时最麻烦的就是手工从结果集中获取数据的过程,这里博主写了一个简单的工具类去做JDBC结果集和对应实体之间的转换,代码如下:
/**
* 转换数据 JDBC结果集转实体
*
* @param resultSet 结果集
* @param clazz 实体字节码文件对象
* @param <T> 实体类型
* @throws Exception sql异常 NoClass异常等等
*/
public static <T> List<T> exchangeData(ResultSet resultSet, Class<T> clazz) throws Exception {
//获取全部类方法 包括父类的
Method[] declaredMethods = clazz.getMethods();
List<T> list = new ArrayList<>();
ResultSetMetaData metaData = resultSet.getMetaData();
while (resultSet.next()) {
//反射实例化对象
T obj = clazz.newInstance();
//遍历类调用方法
for (Method method : declaredMethods) {
//获取方法名
String name = method.getName();
if (!name.startsWith("set")){
//只要setter
continue;
}
//获取数据库名 驼峰命名法转数据库字段命名法
String dbName = getDbName(name);
//遍历数据库所有列
for (int i = 1; i <= metaData.getColumnCount(); i++) {
//抓取指定列赋值
if (metaData.getColumnName(i).equals(dbName)) {
if (resultSet.getObject(i) != null) {
//赋值
setValue(obj,method,resultSet,i);
}
break;
}
}
}
list.add(obj);
}
return list;
}
/**
* 赋值操作,
* 主要是处理数据类型
* 此处只简单处理下基本数据类型和Date类型
* @param obj 泛型对象
* @param method 方法
* @param resultSet 结果集
* @param i 脚标
* @param <T> 泛型
*/
private static <T> void setValue(T obj, Method method, ResultSet resultSet, int i) throws SQLException, InvocationTargetException, IllegalAccessException {
//Setter方法只有一个参数,获取参数类型名称
String name = method.getParameterTypes()[0].getName().toLowerCase();
if (name.contains("string")){
method.invoke(obj, resultSet.getString(i));
}
else if (name.contains("short")){
method.invoke(obj,resultSet.getShort(i));
}
else if (name.contains("int") || name.contains("integer")){
method.invoke(obj,resultSet.getInt(i));
}
else if (name.contains("long")){
method.invoke(obj,resultSet.getLong(i));
}
else if (name.contains("float")){
method.invoke(obj,resultSet.getFloat(i));
}
else if (name.contains("double")){
method.invoke(obj,resultSet.getDouble(i));
}
else if (name.contains("boolean")){
method.invoke(obj,resultSet.getBoolean(i));
}
else if (name.contains("date")){
method.invoke(obj,resultSet.getDate(i));
}
else {
method.invoke(obj, resultSet.getObject(i));
}
}
/**
* 实体setter名称转对应数据库列的列名
* 需要遵守命名规范,java(驼峰命名法),数据库(全小写,单词间用'_'隔开)
* @param name setter名称
* @return 数据库列名
*/
private static String getDbName(String name) {
//根据setter命名规则获取对应的属性名
name = name.substring(3,4).toLowerCase()+name.substring(4);
//获取数据库对应列名
StringBuffer buffer = new StringBuffer();
char[] nameChars = name.toCharArray();
for (char nameChar : nameChars) {
if (nameChar >= 'A' && nameChar <= 'Z') {
//将大写字母转换为下划线和对应的小写字母组合
buffer.append("_").append(String.valueOf(nameChar).toLowerCase());
} else {
buffer.append(String.valueOf(nameChar));
}
}
return buffer.toString();
}
测试代码:
public static void main(String[] args) throws Exception {
Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/my_blog?characterEncoding=UTF" +
"-8", "root", "123123");
String sql = "select * from resource ";
assert connection != null;
PreparedStatement preparedStatement = connection.prepareStatement(sql);
ResultSet resultSet = preparedStatement.executeQuery();
List<Resource> resources = exchangeData(resultSet, Resource.class);
resources.forEach(System.out::println);
}
测试结果:
Resource{id=96, className='RoleResource', classDescription='角色管理接口', action='UPDATE', path='/api/role', description='更新'}
Resource{id=98, className='RoleResource', classDescription='角色管理接口', action='SELECT', path='/api/role', description='分页查询'}
Resource{id=99, className='RoleResource', classDescription='角色管理接口', action='DELETE', path='/api/role/{id}', description='删除单个'}
Resource{id=100, className='RoleResource', classDescription='角色管理接口', action='SELECT', path='/api/role/{id}', description='查询单个'}
Resource{id=101, className='RoleResource', classDescription='角色管理接口', action='DELETE', path='/api/role', description='批量删除'}
Resource{id=102, className='RoleAccessResource', classDescription='角色权限接口', action='UPDATE', path='/api/roleAccess', description='更新'}
Resource{id=103, className='RoleAccessResource', classDescription='角色权限接口', action='ADD', path='/api/roleAccess', description='新增'}
Resource{id=104, className='RoleAccessResource', classDescription='角色权限接口', action='SELECT', path='/api/roleAccess', description='分页查询'}
Resource{id=105, className='RoleAccessResource', classDescription='角色权限接口', action='DELETE', path='/api/roleAccess/{id}', description='删除单个'}
Resource{id=106, className='RoleAccessResource', classDescription='角色权限接口', action='SELECT', path='/api/roleAccess/{id}', description='查询单个'}
Resource{id=107, className='RoleAccessResource', classDescription='角色权限接口', action='DELETE', path='/api/roleAccess', description='批量删除'}
Resource{id=108, className='UserResource', classDescription='用户管理接口', action='UPDATE', path='/api/user', description='更新'}
Resource{id=109, className='UserResource', classDescription='用户管理接口', action='ADD', path='/api/user', description='新增'}
Resource{id=110, className='UserResource', classDescription='用户管理接口', action='SELECT', path='/api/user', description='分页查询'}
Resource{id=111, className='UserResource', classDescription='用户管理接口', action='DELETE', path='/api/user/{id}', description='删除单个'}
Resource{id=112, className='UserResource', classDescription='用户管理接口', action='SELECT', path='/api/user/{id}', description='查询单个'}
Resource{id=113, className='UserResource', classDescription='用户管理接口', action='DELETE', path='/api/user', description='批量删除'}
Resource{id=114, className='UserResource', classDescription='用户管理接口', action='OTHER', path='/api/user/Logout', description='登出'}
Resource{id=115, className='UserResource', classDescription='用户管理接口', action='OTHER', path='/api/user/addRole', description='给用户添加角色'}
Resource{id=116, className='RoleResource', classDescription='角色管理接口', action='ADD', path='/api/role', description='新增'}
使用比较简单,采用的盆友记得点赞!