• JDBC 连接池下重构操作



    经过对连接池的而学习,我们接下来我们将代码再次进行重构操作
    ps:修改代码的位置都会使用注释表示出来啊

    重构设计下-JDBC操作
    1.修改dom.Impl包下的JDBCUtil使其使用连接池来获取对象
    将原有代码
    private static Properties p = new Properties();
    static {
    try {
    //在静态代码块中对资源文件进行操作
    //先创建ClassLoader类加载器对象,来获取db.properties
    ClassLoader loader = Thread.currentThread().getContextClassLoader();
    //字节流对象
    InputStream in = loader.getResourceAsStream("db.properties");
    //加载文件 Properties对象
    p.load(in);
    } catch (IOException e1) {
    // TODO Auto-generated catch block
    e1.printStackTrace();
    }



    //加载驱动
    try {
    Class.forName(p.getProperty("driverClassName"));
    } catch (ClassNotFoundException e) {
    throw new RuntimeException("数据库加载驱动异常");
    }
    }

    //提供一个连接方法
    public static Connection getConn() {
    try {
    //获取连接对象
    return DriverManager.getConnection(p.getProperty("url"),p.getProperty("username"), p.getProperty("password"));
    } catch (Exception e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    //连接失败:
    throw new RuntimeException("数据库连接异常");

    }


    替换原有为连接池代码
    //1.先创建连接池对象
    private static DataSource ds;
    //druid连接池加载
    static {
    try {
    Properties p = new Properties();
    ClassLoader loader = Thread.currentThread().getContextClassLoader();
    InputStream in = loader.getResourceAsStream("druid.properties");
    //加载文件
    p.load(in);
    //创建对象
    ds = DruidDataSourceFactory.createDataSource(p);

    }catch(Exception e) {
    e.printStackTrace();
    }

    }
    //获取连接对象

    public static Connection getConnection() {
    try {
    return ds.getConnection();
    } catch (SQLException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    throw new RuntimeException("连接异常");
    }

    2.修改dom.Impl包下的StudentDAOImpl类里面的增删改查中的连接对象获取方式使用连接池获取
    将conn = JDBCUtil.getConn();替换为conn = JDBCUtil.getConnection(); 使用这个处理连接方式


    3.针对于DML操作(增删改)来说,不同的是:
    SQL不同:不同操作都需要SQL,仅仅是SQL内容不同.
    占位符参数不同:不同的操作都需要设置占位符参数,仅仅是占位符参数的个数和类型不同.
    所以我们将dom.Impl包下的StudentDAOImpl类插入,删除,更改的代码进行修改
    将插入
    Connection conn = null;
    PreparedStatement ps = null;
    try {
    conn = JDBCUtil.getConn();
    //获取预编译对象
    ps = conn.prepareStatement(sql);
    //赋值
    ps.setString(1, student.getName());
    ps.setInt(2, student.getAge());
    //执行SQL 不要有参数
    int rows = ps.executeUpdate();

    if (rows == 1) {
    System.out.println("插入成功");
    }

    } catch (Exception e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } finally {
    JDBCUtil.close(conn, ps, null);
    }
    将删除
    Connection conn = null;
    PreparedStatement ps = null;
    try {
    conn = JDBCUtil.getConn();
    ps = conn.prepareStatement(sql);
    ps.setInt(1, id);
    int rows = ps.executeUpdate();
    if (rows == 1) {
    System.out.println("删除成功");
    }

    } catch (Exception e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } finally {
    JDBCUtil.close(conn, ps, null);
    }

    将更新
    Connection conn = null;
    PreparedStatement ps = null;
    try {
    conn = JDBCUtil.getConn();
    ps = conn.prepareStatement(sql);
    ps.setString(1, student.getName());
    ps.setInt(2, student.getAge());
    ps.setLong(3, id);
    int rows = ps.executeUpdate();
    if (rows == 1) {
    System.out.println("更新成功");
    }

    } catch (Exception e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } finally {
    JDBCUtil.close(conn, ps, null);
    }


    在dom.Impl包下将JDBCUtil类添加一个通用的增删改
    /**
    * 封装一个通用的DML操作
    * @param sql DML操作具体的SQL,可以insert,update,delete
    * @param params SQL中占位符对应的参数 (使用可变参数的好处就是要么可以什么都不用传,要么可以穿多个参数可以方便使用,使用Object是可以接受任何参数)
    * @return 受影响的行数
    */

    public static int updata(String sql,Object...params) {
    Connection conn = null;
    PreparedStatement ps = null;
    try {
    //这里使用连接池的方式获取连接对象
    conn = JDBCUtil.getConnection();
    ps = conn.prepareStatement(sql);
    //设置占位符参数
    //通过循环的方式将参数都设置进去
    for(int i = 0;i<params.length;i++) {
    //参数因为是使用的Objcet类型所以在设置参数的时候就要使用setObject
    ps.setObject(i+1, params[i]);
    }
    //返回得到的设置参数
    return ps.executeUpdate();

    } catch (Exception e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } finally {
    JDBCUtil.close(conn, ps, null);
    }
    return 0; //失败参数

    }


    然后在dom.Impl包下将StudentDAOImpl类修改
    /*
    * 插入 插入数据
    */
    @Override
    public void save(Student student) {
    String sql = "insert into t_student(name,age)values(?,?)";
    Object[] params = {student.getName(),student.getAge()};
    if(JDBCUtil.updata(sql, params)>0) {
    System.out.println("数据库数插入除成功");
    }

    }

    /*
    * 删除
    */
    @Override
    public void delete(int id) {
    String sql = "delete from t_student where id = ?";
    if (JDBCUtil.updata(sql, id) > 0) {
    System.out.println("数据库数据删除成功");
    }

    }

    /*
    * 更新
    */
    @Override
    public void update(int id, Student student) {
    String sql = "update t_Student set name = ?,age = ? where id = ?";
    Object[] params = {student.getName(),student.getAge(),id};
    if(JDBCUtil.updata(sql, params) > 0) {
    System.out.println("数据库数据更新成功");
    }
    }

    4.根据第3问题的做法同样可以将DQL操作进行修改
    所以我们将dom.Impl包下的StudentDAOImpl类查找的代码进行修改
    将查询所有:
    // 创建一个集合对象 用来存储 查询结果
    List<Student> list = new ArrayList<>();
    Connection conn = null;
    PreparedStatement ps = null;
    ResultSet rs = null;
    try {

    conn = JDBCUtil.getConn();
    ps = conn.prepareStatement(sql);
    rs = ps.executeQuery();

    while (rs.next()) {
    Student stu = new Student();
    // 因为数据库表中的列所对应的值是是可以出现null
    // 这里在做描述类的时候,建议将数据类型使用包装类这样既可以兼容null也可以兼容基本类型
    stu.setId(rs.getLong("id"));
    stu.setName(rs.getString("name"));
    stu.setAge(rs.getInt("age"));
    list.add(stu);
    }

    if (list.size() != 0) {
    return list;

    }

    } catch (Exception e) {

    e.printStackTrace();
    } finally {
    JDBCUtil.close(conn, ps, rs);

    }

    查询一个结果:
    Connection conn = null;
    PreparedStatement ps = null;
    ResultSet rs = null;
    try {

    conn = JDBCUtil.getConn();
    ps = conn.prepareStatement(sql);
    ps.setLong(1, id);
    rs = ps.executeQuery();


    // 将结果集中的对象取出来
    while (rs.next()) {
    Student stu = new Student();
    stu.setId(rs.getLong("id"));
    stu.setName(rs.getString("name"));
    stu.setAge(rs.getInt("age"));
    return stu;
    }

    } catch (Exception e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } finally {
    JDBCUtil.close(conn, ps, rs);
    }

    在dom.Impl包下将JDBCUtil类添加一个通用的查找
    /**
    * DQL操作模板
    * @param sql DQL操作具体的SQL,select
    * @param params SQL中占位对应参数
    * @return 查询结果
    */
    public static List<Student> query(String sql,Object... params){
    // 创建一个集合对象 用来存储 查询结果
    List<Student> list = new ArrayList<>();
    Connection conn = null;
    PreparedStatement ps = null;
    ResultSet rs = null;
    try {
    //这里使用连接池的方式获取连接对象
    conn = JDBCUtil.getConnection();
    ps = conn.prepareStatement(sql);
    //设置占位符参数
    //通过循环的方式将参数都设置进去
    for(int i = 0;i<params.length;i++) {
    //参数因为是使用的Objcet类型所以在设置参数的时候就要使用setObject
    ps.setObject(i+1, params[i]);
    }
    rs = ps.executeQuery();

    while (rs.next()) {
    Student stu = new Student();
    // 因为数据库表中的列所对应的值是是可以出现null
    // 这里在做描述类的时候,建议将数据类型使用包装类这样既可以兼容null也可以兼容基本类型
    stu.setId(rs.getLong("id"));
    stu.setName(rs.getString("name"));
    stu.setAge(rs.getInt("age"));
    list.add(stu);
    }

    } catch (Exception e) {

    e.printStackTrace();
    } finally {
    JDBCUtil.close(conn, ps, rs);

    }

    return list;
    }


    然后在dom.Impl包下将StudentDAOImpl类修改

    /*
    * 查询
    */

    @Override
    public List<Student> list() {
    // SQL语句
    String sql = "select * from t_student";
    return JDBCUtil.query(sql);
    }

    /*
    * 单独查询
    */
    @Override
    public Student get(int id) {
    String sql = "select * from t_student where id= ?";
    List<Student> list = JDBCUtil.query(sql, id);
    //判断时候取回值,若取会值就返回,没有就是null
    return list.size() == 1 ? list.get(0) : null;

    }


    ps:写上面这些代码时为了让你们明白是从什么位置开始修改,修改成样式,下面的修改就直接体现咋代码中了


    5.抽取的DQL操作模板,仅仅只能适用于操作t_student表和Student对象.
    如果现在需要操作另一张表(t_teacher),把t_teacher表中的每一行数据封装成Teacher对象.
    此时JDBCUtil的query方法再不再通用.
    我们不应该把处理结果集的代码放入到JDBCUtil中,因为针对于不同的表处理结果集的方式是不一样的.(因为表的列是不同的)
    因为不同DAO处理不同的表(处理不同的结果集),所以我们应该把处理结果集的行为交给每一个DAO的实现类,不应该存放在JDBCUtil中.
    所以会先指定处理结果集的规范:
    1.在dao包中创建一个接口IResultSetHandler来做通用结果集
    2.声明StudentResultSetHandler类来实现这个结果集
    ps:StudentResultSetHandler类其实不需要单独声明成一个类,因为这个类就是为了StudentDAOImpl这个类实现的,所以,可以作为当前类的内部类
    在dom.Impl包下修改JDBCUtil和StudentDAOImpl类


    到这里为止我们将JDBC的封装已经做完了,剩余的让大家上的让其通用可以参考通用结果集处理的办法
    ps:在实际开发中我们会这对具体的表做到具体的业务,要做单万物都通的话我们还需要用到更多的技术反射,泛型和内省(Introspector)
    这里的JDBCUtil其实就是市面上的-->BDUtil只不过我们封装的更加具体而已,并且是DAO的概念给了大家
    最后下一周的Linux要好好学习,我们Hadoop见.......

  • 相关阅读:
    java.lang.Object中的方法
    lyt经典版MySQL基础——进阶3:排序查询
    lyt经典版MySQL基础——进阶5:分组查询
    lyt经典版MySQL基础——DML语言-数据的插入、修改、删除操作
    lyt经典版MySQL基础——进阶8:联合查询
    lyt经典版MySQL基础——进阶7:子查询
    lyt经典版MySQL基础——进阶6:连接查询-sql99语法-内连接、外连接、交叉连接
    lyt经典版MySQL基础——进阶6:连接查询-sql92语法-内连接
    lyt经典版MySQL基础——进阶4:常见函数-分组函数
    lyt经典版MySQL基础——进阶2:条件查询
  • 原文地址:https://www.cnblogs.com/lijun199309/p/9664428.html
Copyright © 2020-2023  润新知