当前位置:Gxlcms > 数据库问题 > JDBC框架的编写

JDBC框架的编写

时间:2021-07-01 10:21:17 帮助过:3人阅读

class Account { private int id; private String name; private double money; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getMoney() { return money; } public void setMoney(double money) { this.money = money; } }

在未使用框架时编写AccountDAO

public void insertAccount(Account account) {
        Connection conn = null;
        PreparedStatement stmt = null;

        try {
            conn = JDBCUtils.getConnection();
            String sql = "insert into account values(null,?,?)";

            stmt = conn.prepareStatement(sql);
            // 设置参数
            stmt.setString(1, account.getName());
            stmt.setDouble(2, account.getMoney());

            stmt.executeUpdate();

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.release(stmt, conn);
        }
    }

通过不同对象DAO模式下的SQL操作比较对方法进行提取编写通用框架

public static void update(String sql, Object... args) {
        Connection conn = null;
        PreparedStatement stmt = null;

        try {
            conn = JDBCUtils.getConnection();

            stmt = conn.prepareStatement(sql);
            // 设置参数 --- 根据?设置参数
            ParameterMetaData parameterMetaData = stmt.getParameterMetaData();
            int count = parameterMetaData.getParameterCount();
            for (int i = 1; i <= count; i++) {
                stmt.setObject(i, args[i - 1]);
            }

            stmt.executeUpdate();

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.release(stmt, conn);
        }
    }

在使用框架之后写的AccountDAO

public void insertAccount(Account account) {
    String sql = "insert into account values(null,?,?)";
    Object[] params={account.getNmae(),account.getMoney()}
    JDBCFramework.update(sql,params)
    

}

通用框架的编写使用在后来可以不断重复使用,大大的简化了开发。但是上面的通用框架方法只适合CUD增删改,对于查询R来说是不能使用的,所以需要单独进行抽取编写框架方法

在未使用框架时

public Account findById(int id) {
     Connection conn = null;
     PreparedStatement stmt = null;
     ResultSet rs = null;
    Account account = null;
    
     try {
    conn = JDBCUtils.getConnection();
    String sql = "select * from account where id = ?";
    
     stmt = conn.prepareStatement(sql);
    
    //设置参数
    stmt.setInt(1, id);
    
     rs = stmt.executeQuery();
    if (rs.next()) {
    account = new Account();
    account.setId(rs.getInt("id"));
    account.setName(rs.getString("name"));
     account.setMoney(rs.getDouble("money"));
    }

    } catch (SQLException e) {
    e.printStackTrace();
     } finally {
    JDBCUtils.release(rs, stmt, conn);
     }
    
     return account;
     }

编写框架

public static <T> T query(String sql, MyResultSetHandler<T> handler,
            Object... args) {
        T obj = null;

        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;

        try {
            conn = JDBCUtils.getConnection();
            stmt = conn.prepareStatement(sql);

            // 设置参数
            ParameterMetaData parameterMetaData = stmt.getParameterMetaData();
            int count = parameterMetaData.getParameterCount();
            for (int i = 1; i <= count; i++) {
                stmt.setObject(i, args[i - 1]);
            }

            rs = stmt.executeQuery();
            obj = handler.handle(rs);

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.release(rs, stmt, conn);
        }
        return obj;
    }

要另外定义接口将rs结果集中的数据封装成一个对象

public interface MyResultSetHandler<T> {
    // 将rs中数据封装对象
    public T handle(ResultSet rs);
}

使用框架之后

public Account findById(int id) {
        // 使用自定义框架
        String sql = "select * from account where id = ?";
        MyResultSetHandler handler = new MyResultSetHandler() {//内部类实现框架的接口封装数据。但是每次都要实现 MyResultSetHandler接口,手动完成数据的封装的动作,所以此动作依然可以继续向上抽取。
            @Override
            public Object handle(ResultSet rs) {
                try {
                    if (rs.next()) {
                        Account account = new Account();
                        account.setId(rs.getInt("id"));
                        account.setName(rs.getString("name"));
                        account.setMoney(rs.getDouble("money"));
                        return account;
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                return null;
            }
        };

        return (Account) JDBCFramework.query(sql, handler, id);
    }
内部类实现框架的接口封装数据。但是每次都要实现 MyResultSetHandler接口,手动完成数据的封装的动作,所以此动作依然可以继续向上抽取。
将封装结果集数据的动作进行向上提取,利用泛型和反射在框架中编写通用的Handler程序,☆难点。
public class MyBeanHandler<T> implements MyResultSetHandler<T> {

    private Class<T> domainClass;

    public MyBeanHandler(Class<T> domainClass) {//泛型是存在编译时期的,要创建T泛型的实例,需要将具体类的字节码文件对象传入利用反射技术去创建对象。
        this.domainClass = domainClass;
    }

    @Override
    public T handle(ResultSet rs) {//用泛型去指代返回的数据类型。
        try {
            ResultSetMetaData resultSetMetaData = rs.getMetaData();// 结果集元数据
            int count = resultSetMetaData.getColumnCount();

            BeanInfo beanInfo = Introspector.getBeanInfo(domainClass);//使用内省技术获得字节码文件对象的属性描述器。
            PropertyDescriptor[] descriptors = beanInfo
                    .getPropertyDescriptors();
            if (rs.next()) {
                T t = domainClass.newInstance();//此处获得T的实例对象
                for (int i = 1; i <= count; i++) {
                    String columnName = resultSetMetaData.getColumnName(i);
                    // 获得列名 --- 需要去查找匹配属性
                    for (PropertyDescriptor propertyDescriptor : descriptors) {
                        if (columnName.equals(propertyDescriptor.getName())) {
                            // 列名 存在 同名属性 ---- 列值 存到属性里
                            Method writeMethod = propertyDescriptor
                                    .getWriteMethod(); // setName setMoney
                            writeMethod.invoke(t, rs.getObject(columnName));
                        }
                    }
                }
                return t;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}

最后简化出的DAO下的查询方法

public Account findById(int id) {
        String sql = "select * from account where id = ?";
        return JDBCFramework.query(sql,new MyBeanHandler<Account>(Account.class),id)
}

 

JDBC框架的编写

标签:

人气教程排行