网站制作公司司,抖音开放平台是干什么的,空调安装东莞网站建设,wordpress 分类文章列表分页将ResultSet转实体类
sqlExecutor.executeQuery的执行结果的返回值是ResultSet:package java.sql;
一般在程序中我们需要把查询结果转为实体类返回给前端#xff0c;此处可以使用的方法#xff1a;
ResultSet转实体类方法1 2
1#xff1a;resultSet.getXXX(columnIndex)…将ResultSet转实体类
sqlExecutor.executeQuery的执行结果的返回值是ResultSet:package java.sql;
一般在程序中我们需要把查询结果转为实体类返回给前端此处可以使用的方法
ResultSet转实体类方法1 2
1resultSet.getXXX(columnIndex) 根据列的序号依次取值并赋值给实体类的具体属性
定义一个实体类比如EntityDefine.class
public class EntityDefine implements Serializable {private static final long serialVersionUID 3394089767543785764L;// 定义属性private String key;private Integer count;private Date updateTime;...;// get set 方法public String getKey(){return this.key;}public String setKey(String key) {this.key key;}...;
}定义一个处理ResultSet的方法handleResultSet
private EntityDefine handleResultSet(ResultSet resultSet) throws SQLException {EntityDefine entity new EntityDefine();int col 1;// 字符型entity.setKey(resultSet.getString(col));// 整型entity.setCount(resultSet.getInt(col));// 时间戳entity updateTime resultSet.getTimestamp(col);entity.setUpdateTime(updateTime);entity.setXXX(resultSet.getString(col));return entity;
}以上即可将ResultSet转为实体类。
优点是简单
缺点是需要对ResultSet中的数据提前调试确定每一列对应的属性一般和数据库列的顺序一致
2实体类注解反射
注解是一种在Java中用来提供元数据的工具它们可以在编译时和运行时为代码添加信息并且可以被反射机制获取和处理。
1首先我们定义一个注解用在实体类的所有属性上都加上;
需要在注解中声明对应的数据库字段名
属性对应的get方法可以编码时直接给出如果属性值过多则配置会麻烦或者用方法动态拼接例子用这种方法
Retention(RetentionPolicy.RUNTIME)
Target(ElementType.FIELD)
public interface MyResultSetFiled {/** 对应的数据库字段名 */String dbFiled();Class? fieldType() default String.class;/** 属性对应的get方法 */String get() default ;/** 是否需要自动补充当前时间 */boolean autoDate() default false;
}关于注解 注解按生命周期来划分可分为3类 1、RetentionPolicy.SOURCE注解只保留在源文件当Java文件编译成class文件的时候注解被遗弃 2、RetentionPolicy.CLASS注解被保留到class文件但jvm加载class文件时候被遗弃这是默认的生命周期 3、RetentionPolicy.RUNTIME注解不仅被保存到class文件中jvm加载class文件之后仍然存在 这3个生命周期分别对应于Java源文件(.java文件) — .class文件 — 内存中的字节码。 那怎么来选择合适的注解生命周期呢 首先要明确生命周期长度 SOURCE CLASS RUNTIME 所以前者能作用的地方后者一定也能作用。 一般如果需要在运行时去动态获取注解信息那只能用 RUNTIME 注解 如果要在编译时进行一些预处理操作比如生成一些辅助代码如 ButterKnife就用 CLASS注解 如果只是做一些检查性的操作比如 Override 和 SuppressWarnings则可选用 SOURCE 注解。 Target 指的是注解的作用目标。 Target(ElementType.TYPE)——接口、类、枚举、注解 Target(ElementType.FIELD)——字段、枚举的常量 Target(ElementType.METHOD)——方法 Target(ElementType.PARAMETER)——方法参数 Target(ElementType.CONSTRUCTOR) ——构造函数 Target(ElementType.LOCAL_VARIABLE)——局部变量 Target(ElementType.ANNOTATION_TYPE)——注解 Target(ElementType.PACKAGE)——包 2定义一个实体类比如EntityDefine.class
public class EntityDefine implements Serializable {private static final long serialVersionUID 3394089767543785764L;// 定义属性,并添加注解MyResultSetFiled(dbFiled key)private String key;MyResultSetFiled(dbFiled count)private Integer count;MyResultSetFiled(dbFiled update_time)private Date updateTime;...;// get set 方法public String getKey(){return this.key;}public String setKey(String key) {this.key key;}...;
}注意此处dbFiled要是数据库中的字段名一般是采用下划线命名法与实体类中定义属性的驼峰命名法有所区别。
可以将dbFiled后面跟的这些值封装成常量便于维护。
3定义一个抽象类在此方法中直接给类的各种属性封装好对应的值所以建议做成构造函数的实现形式
public abstract class ResultSetWrapper implements Serializable{private static final long serialVersionUID -2088813051606973972L;/*** 给给定的类的属性赋值根据注解获取数据库的字段从ResultSet中获取对应的值value* 动态拼接对应属性的Set方法* 利用反射执行Set方法将value赋值给对应的属性* 此方法没有返回值给定的对象在该方法中执行一遍set后返回* param resultSet 数据库查询结果集* param clazz 要转化的实体类*/public void setData(ResultSet resultSet, Class? clazz) {try {// 获取类中所有定义的属性Field[] fields clazz.getDeclaredFields();// 遍历for(Field field : fields) {// 获取属性上的注解信息MyResultSetFiled resultSetFiled field.getAnnotation(AuditField.class);if(resultSetFilednull) continue;// resultSet.getObject(列名)// 此方法可以配合我们获取注解中的数据库字段名使用来获取对应的列的值Object value resultSet.getObject(resultSetFiled.dbFiled());// 动态凭借对应属性的Set方法String fieldSetName parSetName(field.getName());// 反射获取方法Method fieldSetMet clazz.getMethod(fieldSetName, field.getType());if (null ! value !.equals(value)) {String fieldType value.getClass().getSimpleName();// 根据value的不同String, Int, Data等执行不同的set方法即invoke(this, value)if (String.equals(fieldType)) {fieldSetMet.invoke(this, value);} else if (CLOB.equals(fieldType)) {// Clob转String见第三部分《Clob转String》介绍String strClob ClobToString((Clob) value);fieldSetMet.invoke(this, strClob);} else if (Date.equals(fieldType) || TIMESTAMP.equals(fieldType)) {Date temp parseDate(value.toString());fieldSetMet.invoke(this, temp);} else if (Integer.equals(fieldType)|| int.equals(fieldType)) {Integer intval Integer.parseInt(value.toString());fieldSetMet.invoke(this, intval);} else if (Long.equalsIgnoreCase(fieldType)) {Long temp Long.parseLong(value.toString());fieldSetMet.invoke(this, temp);} else if (Double.equalsIgnoreCase(fieldType)) {Double temp Double.parseDouble(value.toString());fieldSetMet.invoke(this, temp);} else if (Boolean.equalsIgnoreCase(fieldType)) {Boolean temp Boolean.parseBoolean(value.toString());fieldSetMet.invoke(this, temp);} else {System.out.println(not supper type fieldType);}}}}catch(NoSuchMethodException|SecurityException|IllegalAccessException|IllegalArgumentException|InvocationTargetException|SQLException e) {}}/*** 拼接在某属性的 set方法* param fieldName 字段名* return String setXXX*/private String parSetName(String fieldName) {if (null fieldName || .equals(fieldName)) {return null;}return set fieldName.substring(0, 1).toUpperCase() fieldName.substring(1);}}实体类EntityDefine.class完善继承上述抽象类并在构造方法中声明
public class EntityDefine extends ResultItem {...;public EntityDefine() {}// 构造方法public EntityDefine (ResultSet resultSet){super();this.setData(resultSet, EntityDefine.class);}...;}4程序中处理
new EntityDefine(resultSet);即可获取到一个被完整赋值的对象实例
优点定义好了注解、构造函数之后在使用时直接new 即可非常方便
缺点配置复杂
Clob转String
在ResultSet转实体类中存在Clob类型转换问题需要转为String /*** CLOB转String* param clob clob* return 字符串*/
public static String ClobToString(Clob clob) {String reString ;try {// 得到流Reader is clob.getCharacterStream();BufferedReader br new BufferedReader(is);String s br.readLine();StringBuilder sb new StringBuilder();// 执行循环将字符串全部取出付值给StringBuilder由StringBuilder转成STRINGwhile (s ! null) {sb.append(s).append(\n);s br.readLine();}reString sb.toString();} catch (SQLException|IOException e) {e.printStackTrace();}return reString;
}