• 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)+"	"
                            +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);
    
    
  • 相关阅读:
    (转)JQuery中$.ajax()方法参数详解
    __dopostback的用法 . 编辑
    (转)__dopostback的用法 .
    (转)如何区分一个程序员是“老手“还是“新手“?
    jQuery验证框架 .
    location.href的用法
    为用户设置密码
    设置环境变量
    用 xampp 在ubuntu 下配置php 运行环境 lampp
    安装与配置JDK
  • 原文地址:https://www.cnblogs.com/biturd/p/12623149.html
Copyright © 2020-2023  润新知