开发者学堂课程【DAO 开发实战业务分析:OR-Mapping 设计改进(主键查询改进)】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/399/detail/5181
OR-Mapping 设计改进(主键查询改进)
内容介绍:
一、简述
二、具体内容
一、简述
在整个 JDBC 的开发之中对于数据的取出实际上是有一个严重的性能问题的,理论上不需要的数据不应该取出,如果要想达到这样的目的,就必须针对于整体操作进行一些规划,如果需要设置要查询的列,则这个设置过程应该交由用户处理,也就是说用户要负责生成 SQL 语句。
二、具体内容
1、在 AbstractDAO 类里面追加一个处理的方法。找到 findById,返回的一定是位型,跟上public <T> T findByIdSupport(String sql,String Value,Class<T> cls) throws Exception {},要求能接收 sql 与value,Class 是一定要有的,否则值不能返回。
首先要改的部分在于return super.findByIdSupport(sql,id,Member.class);。
再在上方写出注释,而在将查询结果自动转为VO类流程的过程中的关键因素为查询全部的操作也要经过这种转换。
如下:
/**
* 对数据的查询进行控制
* @param sql 要执行的根据ID查询的SQL语句
* @param value 要查询的id数据
* @param cls 要处理的VO类型
* @return 查询到数据则将ResultSet的内容自动转换为VO对象返回
* @throws Exception
*/
public <T,V> T findByIdSupport(String sql,V value,Class<T> cls) throws Exception {
return null ;
}
2、在子类里面需要负责好要使用的 SQL 语句。
Iterator<?> iter = ids. iterator() ;
int foot = 1 ;
while (iter.hasNext()) {
buf.append(“?,”) ;
this.valueMap.put(foot ++,iter.next()) ;
}
buf.delete(buf.length() - 1, buf.length()) ;
buf. append(“(“) ;
return buf.toString() ;
}
}
3、在 AbstractDAO 父类里面实际上对于 SQL 不再需要自动生成了,而后只需要考虑设置内容即可,而且主键的类型往往是 String 或者是 Integer(Int)。
在 FindSupport 中,在追加处理方法的部分中,并不知道主键的类型,但是可以通过 Class 资源文件找到主键的列与属性,再通过属性找到属性的类型。
而在这个地方并不能跟String而是跟泛型,即改为 public <T,V> T findByIdSupport(String sql,V value,Class<T> cls) throws Exception {,而有了 T 和 value 则不需要通过反射去寻找,而能够直接找到位型。
通过 System.out.println(value.getClass().getSimpleName());来进行验证是可以找到位型的。
然后将值给 FIndSupport 来执行,如下:
package cn.mldn.util.dao.support;
import java.sql.PreparedStatement ;
public class FindSupport {
public <V> void setPreparedStatement(PreparedStatement pstmt,V value) {
String type = value.getClass().getSimpleName() ;
if (“String”.equals(type)) {
pstmt.setString(1,value.toString()) ;
}else if (“Int”.equals(type) || “Integer”.equals(type))
pstmt.setInt(2,parseInt(value.toString())) ;
}
}
}
4、但是现在不是一个查询可以解决的问题,整个过程之中需要将 ResultSet 的数据变为 VO 数据保存,所以此处就需要一个 ResultToVO 的工具类。
知道元数据的目的是为了得到列名称,有了列名称就可以找到属性名称。而数据取出要通过对象来进行实例化控制,
如下:
package cn.mldn.util.dao;
public class ResultSetToVOUtil {
private ResultSetToVOUtil() {}
/**
* 将ResultSet中的内容进行一个转换处理
* @param pstmt 包含有元数据以及可以执行查询的处理对象
* @param cls 要转换的VO对象
* @return
*/
public static <T> T convertSingle(PreparedStatement pstmt,Class<T> cls) {
ResultSetMetaData rsmd = pstmt.getMetaData ;
ResultSet rs = pstmt.executeQuery() ; // 发出查询命令
T t = cls.newInstance() ;
if(rs.next()) { // 有数据
for (int x = 1; x < rsmd.getColumnCount() ; x ++) {
Field field = cls.getDeclaredField(rsmd.getColumnLabel(x).toLowerCase());
String type = field.fetType().getSimpleName() ;
if(“String”.equals(type)) {
BeanValueUtils.setValue(t,rsmd.getColumnLabel(x).toLowerCase(),rs.getString(rsmd.getColumnLabel(x)));
}else if(“int“.equals(type) || “integer“.equals(type)) {
BeanValueUtils.setValue(t,rsmd.getColumnLabel(x).toLowerCase(),rs.getInt(rsmd.getColumnLabel(x)));
}else if(“double“.equals(type) || “Double “.equals(type)) {
BeanValueUtils.setValue(t,rsmd.getColumnLabel(x).toLowerCase(),rs.getDouble(rsmd.getColumnLabel(x)));
}else if(“Date“.equals(type) || “integer“.equals(type)) {
BeanValueUtils.setValue(t,rsmd.getColumnLabel(x).toLowerCase(),rs.getDate(rsmd.getColumnLabel(x)));
}
return null ;
}
}
}
测试操作后,显示索引丢失,跟上FindSupport support = new FindSupport();,再跟上
support.setPreparedStatement(this.pstmt,value);后再次执行,没有出错但没有值,再跟上 system.out.println(obj);,执行成功。
5、需要在 BeanValueUtils 类中追加一个根据对象使用相应的setter方法的调用操作。通过 setValue ,即 public static void setValue(Object obj,String attributeName) {来专门设置内容,知道属性名称就可以知道参数位型。
再找到
Fieldfield = obj.getClass().getDeclaredField(attributeName);,
然后就可以知道属性位型,再找到field.getype()进行完善。此外需要完善内容的设置,跟上Object value,
再找到
setMethod.invoke(obj,value);,就可以实现setter调用操作,如下:
public static void setValue(Object obj,String attributeName) {
try {
Field field = obj.getClass().getDeclaredField(attributeName);
Method setMethod = obj.getClass().getMethod(“set” + StringUtils.initcao(attributeName())) ;
setMethod.invoke(obj,value);
} catch (Exception e) {
e.printStackTrace() ;
}
}
6、实现方法的整合调用:
/**
* 对数据的查询进行控制
* @param sql 要执行的根据ID查询的SQL语句
* @param value 要查询的id数据
* @param cls 要处理的VO类型
* @return 查询到数据则将ResultSet的内容自动转换为VO对象返回
* @throws Exception
*/
public <T,V> T findByIdSupport(String sql,V value,Class<T> cls) throws Exception {
FindSupport support = new FindSupport();\
this.pstmt = this.conn.preparedStatement(sql);
support.setPreparedStatement(this.pstmt,value);
returnResultSetToVOUtil.convertSingle(this.pstmt,cls);
}
要想实现一些自动化的控制,必须依靠元数据,而且使用反射最大的亮点在于不受到具体类型的限制。