• 前段时间学习了java的反射机制,感觉很有用,恰逢今天在学习JDBC技术,通过JDBC从数据库中查询的数据在转成自己需要的实体对象,虽然并不难,但是会比较麻烦,而且实体较多的情况下会写大量重复性的代码,很没有效率。所以就想到了反射技术,所以就利用反射技术实现了一个非常简陋的对象关系映射。 

  • 1. 首先是实体类,一个非常简单实体(目前只支持String类型的字段),不过字段的名称要和数据库的表中定义的字段名一致!!
• //城市实体类 public class city {
    //城市简称  private String short_name;
    //城市名称  private String city_name;
    //创建人名称  private String create_name;

    public String getShort_name() {
        return short_name;
    }

    public void setShort_name(String short_name) {
        this.short_name = short_name;
    }

    public String getCity_name() {
        return city_name;
    }

    public void setCity_name(String city_name) {
        this.city_name = city_name;
    }

    public String getCreate_name() {
        return create_name;
    }

    public void setCreate_name(String create_name) {
        this.create_name = create_name;
    }
}
  • 2.接下来是加载JDBC驱动,因为JDBC相关的相关的API会重复的用到,就单独封装到了一个工具类。
public class DBConnection {
    private static Connection connection = null;
    //加载JDBC驱动并获取连接对象
    public static Connection getConnection() {
        if (connection == null) {
            synchronized (DBTest.class) {
                if (connection == null) {
                    try {
                        com.mysql.jdbc.Driver driver = new com.mysql.jdbc.Driver();
                        connection = DriverManager.getConnection("jdbc:mysql://localhost/jeecg", "root", "chielec");
                        // connection.setAutoCommit(false);
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return connection;
    }
    //关闭操作
    public static void closeAll(Connection connection, Statement statement, ResultSet resultSet) {
        try {
            if (connection != null) {
                connection.close();
            }
            if (statement != null) {
                statement.close();
            }
            if (resultSet != null) {
                resultSet.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (connection != null) {
                    connection.close();
                }
                if (statement != null) {
                    statement.close();
                }
                if (resultSet != null) {
                    resultSet.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    } }
  • 3.然后就开始通过反射来实现对象的映射了
  • 在该工具类中声明了3个变量,第一个是映射实体类,第二个是与实体类对应的SQL查询语句,第三个就是字节码了。前两个变量通过构造函数传递进来,然后泛型T就确定了,即传递进来的实体类。这里必须使用泛型,因为实体类是不确定的,同时使用泛型的话就回适用更多的实体类。然后调用实体类的getClass()得到字节码。
public class ORMUtil<T> {

    //映射实体类
    private T entity;
    //查询的Sql语句
    private String selectSql;

    private Class clazz;


    public ORMUtil(T entity, String selectSql) {
        this.entity = entity;
        this.selectSql = selectSql;
        loadClass();
    }

    protected void loadClass() {
        clazz = entity.getClass();
  •    通过clazz调用getDeclaredFields()方法获取实体类中自己定义的所有字段,得到是一个数组,便利数组,调用字段的getName()方法得到字段的名称,保存到集合中并返回。
protected List<String> getFiled() {
    ArrayList<String> list = new ArrayList<>();
    Field[] fields = clazz.getDeclaredFields();
    for (Field filter : fields) {
        String filedName = filter.getName();
        list.add(filedName);
    }
    return list;
}
  •   然后开始查询数据,JDK1.5之后可以使用静态导入,调用getConnection()得到数据库连接对像之后,再调用prepareStatement()执行Sql语句,遍历得到的ResultSet
    集合。这里将每一个对象的字段 以字段的值保存到Map集合中,key对应字段,value对应字段的值,最后在将Map集合保存的List集合中,每一个Map都相当于一个对象。
• protected List<Map<String, String>> selectData(List<String> filedNames) {

    ArrayList<Map<String, String>> list = new ArrayList<>();
    try {
        PreparedStatement preparedStatement = getConnection().prepareStatement(selectSql);
        ResultSet resultSet = preparedStatement.executeQuery();
        while (resultSet.next()) {
            Map<String, String> map = new Hashtable<>();
            for (String fileName : filedNames) {
                map.put(fileName, resultSet.getString(fileName));
            }
            list.add(map);
        }
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
    }
    return list;
}

method.invoke(t, entry.getValue());这里就是方法调用对象(自己是这样理解的哈!),第一个参数是操作的对象,第二个参数是可变数组,即方法的实际参数。

public List<T> getList() {
    List<T> Objects = new ArrayList<>();
    List<Map<String, String>> list = selectData(getFiled());

    for (Map<String, String> map : list) {
        T t = null;
        try {
            //反射是属性操作对象,所以是需要对象的。
            t = (T) clazz.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        for (Map.Entry<String, String> entry : map.entrySet()) {
            try {
                //这里需要对Key(也就是字段进行处理,set后的第一个字母应该大写)
                Method method = clazz.getDeclaredMethod(getMethodName(entry.getKey()    ), String.class);
                method.invoke(t, entry.getValue());
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
        Objects.add(t);
    }
    return Objects;
}
//拼接方法名称
protected String getMethodName(String methodeName) {

    return "set" + methodeName.substring(0, 1).toUpperCase() + methodeName.substring(1);
}
    • 最最后在测试一下
    }@Test
    public void testORMUtil() {
            ORMUtil<city> ormUtil =
                    new ORMUtil<>(new city(),
                            "select  short_name,city_name,create_name from city");
            List<city> list = ormUtil.getList();
            for (city city:list){
                System.out.println(city.getShort_name()+" "
                        +city.getCity_name()+" "+city.getCreate_name());
            }
    }测试结果如下:

    济 济宁 管理员
    汶 汶川 会员
    德 德州 管理员
    汶 汶上 会员==========================================================================================
      • 第一次写博客,其中难免有考虑不周的地方,有哪里不正确的地方请大家指出,我会努力改正!!