需求
将ResultSet中的数据直接封装成实体类。
实现思路
- 由实体类获取字段数据
- 由字段数据取对应字段的值
- 反射创建对象,注入属性值
- 保留字段数据,以便下次访问
画渣,见谅~
项目地址:https://gitee.com/zxing2021/orm.git
效果展示
测试代码,关键只有中间几行:
@Test
public void fun1() {
PreparedStatement ps = null;
try {
ps = JDBCUtil.getStatement("select id,name,age from student");
ResultSet rs = ps.executeQuery();
List<Student> list = ResultSetHandler.getList(rs, Student.class);
for (Student student : list) {
System.out.println(student);
}
JDBCUtil.commitAndClose(ps);
} catch (SQLException throwables) {
throwables.printStackTrace();
JDBCUtil.rollbackAndClose(ps);
}
}
运行效果:
字段数据相关
注解@Row
用以指定列名:
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Row {
String value();
}
属性信息的实体类
用以存放属性的信息:
@Data
public class RowInfo {
private final String colName;
private final String attrName;
private final String attrType;
}
解析一个属性:
private RowInfo(Field field) {
Row row = field.getDeclaredAnnotation(Row.class);
if (row != null) {
this.colName = row.value();
this.attrName = field.getName();
this.attrType = field.getType().getSimpleName();
} else {
this.colName = null;
this.attrName = null;
this.attrType = null;
}
}
简单判空:
public Boolean isNull() {
return this.colName == null;
}
解析一个实体类:
public static List<RowInfo> createList(Class target) {
List<RowInfo> result = new ArrayList<>();
for (Field field : target.getDeclaredFields()) {
RowInfo info = new RowInfo(field);
if (!info.isNull()) {
result.add(info);
}
}
return result;
}
从ResultSet中获取该属性的值:
public Object getValue(ResultSet resultSet) throws SQLException {
switch (attrType) {
case "Integer":
return resultSet.getInt(colName);
case "String":
return resultSet.getString(colName);
default:
return null;
}
}
入口
容器,用以存放解析结果,以免每次都要重新解析:
public class ResultSetHandler {
private static final ConcurrentHashMap<Class, List<RowInfo>> map = new ConcurrentHashMap();
}
获取一个类的解析结果:
private static List<RowInfo> getList(Class target) {
List<RowInfo> result = map.get(target);
if (result == null) {
List<RowInfo> parse = RowInfo.createList(target);
map.put(target, parse);
return parse;
} else {
return result;
}
}
入口方法:
public static <E> List<E> getList(ResultSet resultSet, Class<E> target) {
List<E> result = new ArrayList<>();
try {
while (resultSet.next()) {
E e = create(resultSet, target);
result.add(e);
}
} catch (SQLException e) {
e.printStackTrace();
}
return result;
}
创建实体的方法:
private static <E> E create(ResultSet resultSet, Class<E> target) {
E result = null;
try {
result = target.newInstance();
for (RowInfo info : getList(target)) {
Object attr = info.getValue(resultSet);
Method method = target.getMethod("set" + upper(info.getAttrName()), attr.getClass());
method.invoke(result, attr);
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
杂七杂八:
private static String upper(String name) {
return name.substring(0, 1).toUpperCase() + name.substring(1);
}
小结
ORM思想:实体类与数据表一一对应。
此处只是单表映射成实体类。
|