zoukankan      html  css  js  c++  java
  • 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);
    
    
  • 相关阅读:
    HDU 2888 Check Corners (模板题)【二维RMQ】
    POJ 3264 Balanced Lineup(模板题)【RMQ】
    poj 3368 Frequent values(经典)【RMQ】
    SPOJ RPLN (模板题)(ST算法)【RMQ】
    UVA 796 Critical Links(模板题)(无向图求桥)
    UVA 315 Network (模板题)(无向图求割点)
    POJ 2029 Get Many Persimmon Trees (模板题)【二维树状数组】
    poj 3067 Japan 【树状数组】
    POJ 2481 Cows 【树状数组】
    POJ 1195 Mobile phones【二维树状数组】
  • 原文地址:https://www.cnblogs.com/biturd/p/12623149.html
Copyright © 2011-2022 走看看