反射实现 daoImpl

2017-04-21  本文已影响0人  flyHunter雄

代码实现:

/**
* 根据主键查询数据。
* 要求实体类型的属性名称和数据库表的字段名称完全一致。
* 要求实体类型的类名于数据库的表名有直接关系
* 表名 : tb_类名
* @param clazz : 要查询的数据的java类型。 直接可以代表数据          库中的表名和字段名。
* @param id : 要查询的数据的主键。 主键数据为id字段。
*/
  @Override
  public Object getObjectById(Class clazz, Serializable id) {
// 要执行的查询语句
String sql = "";
Connection conn = null;
PreparedStatement pstm = null;
ResultSet rs = null;
// 查询结果
Object result = null;
try{
    Class.forName("oracle.jdbc.driver.OracleDriver");
    conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "test", "test");
    
    conn.setAutoCommit(false);
    
    sql = createGetObjectByIdSQL(clazz);
    System.out.println("sql : " + sql);
    pstm = conn.prepareStatement(sql);
    pstm.setObject(1, id);
    rs = pstm.executeQuery();
    // 处理结果集。
    if(rs.next()){
    // 缺少字段和对象属性的映射
        // Object columnValue = rs.getObject("字段名");
        Method[] methods = clazz.getMethods();
        // 检索方法中的set方法。 将查询的字段值,注入到对象中。
        result = clazz.newInstance();
        for(Method method : methods){
        String methodName = method.getName();
        if(methodName.startsWith("set") && methodName.length() > 3){
            // 获取字段名称
            String columnName = methodName.substring(3);
            // 获取方法的参数表, 判断参数类型。 决定调用什么方法获取字段数据。
            // 如: 参数类型是Integer, 调用getInt方法。
            Object columnValue = null;
            Class[] parameterTypes = method.getParameterTypes();
            if(parameterTypes.length == 1){
            Class type = parameterTypes[0];
            if(type == Integer.class){
                columnValue = rs.getInt(columnName);
            }else if(type == String.class){
                columnValue = rs.getString(columnName);
            }else if(type == Double.class){
                columnValue = rs.getDouble(columnName);
            }else if(type == int.class){
                columnValue = rs.getInt(columnName);
            }
        }
        // 根据字段名称获取字段数据
        // 将查询结果保存在对象result的属性中。
        method.invoke(result, columnValue);
        }
        }
    }
    conn.commit();
}catch(Exception e){
    e.printStackTrace();
                  如果出现异常回滚
        try {
            conn.rollback();
        } catch (SQLException e1) {
            e1.printStackTrace();
        }
}finally{
        //关闭资源
    if(rs != null){
        try {
            rs.close();
        } catch (SQLException e) {
        // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    if(pstm != null){
        try {
            pstm.close();
        } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
        }
    }
    if(conn != null){
        try {
            conn.close();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
return result;
}

反射拼接 sql 字符串

private String createGetObjectByIdSQL(Class clazz){
  // 缺少SQL语法
  StringBuilder builder = new StringBuilder("select ");
  // 拼接字段名, 字段名就是类型的属性名
  // 获取所有方法。 循环方法的数组。 查询已get/set命名的方法。
  Method[] methods = clazz.getMethods();
  String[] columnNames = new String[methods.length];
  for(int i = 0; i < methods.length; i++){
    String methodName = methods[i].getName();
    
    if(methodName.startsWith("get") && methodName.length() > 3 && !methodName.equals("getClass")){
            // 当前方法是需要分析的方法。 将方法名称前缀get去除,其余部分为字段名
            String columnName = methodName.substring(3);
            columnNames[i] = columnName;
            builder.append(columnName);
            builder.append(",");
      }
    }
  // 上述的SQL语法末尾多一个逗号
builder.deleteCharAt(builder.length() - 1);
  // 拼接表名, 表名是tb_类名
  String className = clazz.getName();
  // 截取类的名称。 className : package.name.ClassName
  className = className.substring(className.lastIndexOf(".")+1);
  builder.append(" from tb_"+className);
  // 拼接条件。 条件是主键查询
  builder.append(" where id = ? ");
  return builder.toString();
  }
上一篇 下一篇

猜你喜欢

热点阅读