JDBC(三)、基础代码及优化

一、三个部分

1.获取连接

jdbc:mysql:///abc 等同于 jdbc:mysql://localhost:3306/abc

指的是数据库名称也就是说第三个'/'代表 'localhost:3306/'

2.处理或者预处理语句

参数:
String name = "'or 1 or'";

拼接sql语句.
String sql = "select * from user where name = '"+name+"'";


底层的语句":
select * from user where name = '' or 1 or '';

解决:
    使用PrepareStatement代替Statement
    
    ps = conn.prepareStatenebt(sql)

3.执行查询或者更改

二、整体流程与代码示例及优化过程

从前到后的优化

一开始所有的都在操作类中,创建连接,关闭什么的,具体操作逻辑。

然后抽取出来创建链接,关闭连接放在JdbcUtils里面完成

然后考虑到效率问题,有了数据源[内部封装了一个connection连接池]。相当于数据库与代码的中间对象。所以封装了一个自己的Connection,重写了close方法[放回连接池]。[方法太多,代理模式,反射动态代理]

然后考虑到增删改查代码冗余,抽象为一个AbstractDao抽象类。[模板设计模式,策略设计模式]

核心代码及对象

  • 两操作(两种返回值)

  • 三对象

  • 单例模式工具类

  • 两操作

    • 查询
    • 增删改
    static void query() throws SQLException {
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;
        sql = null;
        
        try {
            sql = "";
            
            conn = JDBCUtils.getConnection();

           // st = conn.createStatement();
            ps = conn.prepareStatement();
            
            rs = st.executeQuery("");

            while (rs.next()){
                System.out.println(rs.getObject(1)+"\t"
                        +rs.getObject("id"));  // 建议用列名
            }
        }finally {
            JDBCUtils.free(rs,st,conn);
        }
    }
    static int update() throws SQLException {
        // 增删改都是update 返回的是一个int 类型,不需要对结果集做处理
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;
        String sql;

        int i;

        try {
            sql = "";

            conn = JDBCUtils.getConnection();

            st = conn.createStatement();

            i = st.executeUpdate(sql);
            // 数据库客户端里面修改的话 就会 显示有多少条受影响 这个同理

        }finally {
            JDBCUtils.free(rs,st,conn);
        }
        return i;
    }
  • 工具类
public final class JDBCUtils {
    private static String url = "jdbc:mysql://localhost:3306/jdbc";
    private static String user = "root";
    private static String password = "root";

    static {
        try {
            Class.forName("com.mysql.jdbc.Driver");  // 保证注册驱动只会做一次
        } catch (ClassNotFoundException e) {
            throw new ExceptionInInitializerError(e);
        }
    }

    private JDBCUtils(){}  // 私有的构造方法保证不能被创建

    public static Connection getConnection(){
        try {
            return DriverManager.getConnection(url,user,password);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void free(ResultSet rs,Statement st,Connection conn){
        try {
            if (rs != null){
                rs.close();  // 如果这一行抛异常 也会进行
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if(st != null){
                    st.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                if(conn != null){
                    try {
                        conn.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

单例模式 https://www.jianshu.com/p/3bfd916f2bb2

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4T3CgL3x-1584434044950)(https://note.youdao.com/yws/res/17336/720E32DB04DB4BF88953905DB6AB79EE)]

注意点

  • rs.getObject(1) // 是数据库语句中列的索引号,也可以写成string字段

  • ps.setString(1,name);

  • connection关掉后通过connection创建的rs、st都无效了

异常处理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CwoNzlf7-1584434044955)(https://note.youdao.com/yws/res/17525/D008973A2188410A87E91FE94E1FC5BD)]

  • 把异常转化为运行时异常(一定不能catch住什么都不做)

Java 从一开始就内置了异常处理,因此你不得不使用它。这是 Java 语言唯一接受的错误报告方法。

如果没有编写适当的异常处理代码,你将会收到一条编译时错误消息。这种有保障的一致性有时会让程序的错误处理变得更容易。

抽象基本类

public abstract class AbstractDao {
    public int update(String sql,Object[] obj){
        try (
                Connection connection = DataSourcePool.getConnection();
                PreparedStatement preparedStatement =
                        connection.prepareStatement(sql);
                ResultSet resultSet = null;
                // 这一点还是传统写法比较好,  不用传统的注意也行只要重写close方法,不迷就行
                // 因为Connection关闭的方法都变了,重写aotuclose接口的方法
                ){
            int a = 0;
            for(Object i : obj){
                preparedStatement.setObject(++a,obj);
            }
            return preparedStatement.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException();
        }

        /**
         * 实体dao继承abstract
         *
         *     public int update(User user){
         *         String sql = "update user set name=?,birthday=? where id=?";
         *         Object[] args = new Object[]{
         *                 user.getName(),user.getBirthday(),user.getId()
         *         };
         *         super.update(sql,args);
         *     }
         * */
    }
    public Object find(String sql,Object[] objArr){
        try (
                Connection connection = DataSourcePool.getConnection();
                PreparedStatement preparedStatement =
                        connection.prepareStatement(sql);
                ResultSet resultSet = preparedStatement.executeQuery();
                // 这一点还是传统写法比较好,  不用传统的注意也行只要重写close方法,不迷就行
                // 因为Connection关闭的方法都变了,重写aotuclose接口的方法
        ){
            int a = 0;
            for(Object i : objArr){
                preparedStatement.setObject(++a,objArr);
            }
            Object object = null;
            while (resultSet.next()){
                object = mapperRow(resultSet);
            }  // 这点的逻辑 因为要根据查询结果拼成一个对象 但是父类不知道对象的样子
            // 交给子类处理 处理好返回就行  子类需要实现此抽象方法
            return object;
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException();
        }

        /**
         *     public Object mapperRow(ResultSet resultSet){
         *         User user = new User();
         *         user.setId(1,resultSet.getInt("Id"));
         *         return user;
         *     };
         *     public Object find(){
         *         String sql = "select * from user where id=?";
         *         Object[] args = new Object[]{
         *                 user.getId()
         *         };
         *         Object user = super.find(sql,args);
         *         return (User)user;
         *     }
         * */

    }

    public abstract Object mapperRow(ResultSet resultSet);

posted @ 2020-03-17 16:34  Biturd  阅读(5)  评论(0编辑  收藏  举报