JDBCUtils工具类

JDBCUtils工具类

JDBC简介:

JDBC(Java Database Connectivity),Java数据库连接,一组使用Java语言操作数据库的规范(访问不同DBMS的底层方法是不一样的,JDBC把访问数据库的方法进行了统一,访问MYSQL、Oracle、DB2等不同数据库的用法几乎一模一样),具体表现在java.sql包下的一组API

主流数据库厂商都提供了操作自己数据库的JDBC实现,具体表现在数据库驱动jar包,比如MySQL数据库提供的mysql-connector-java.jar

对于开发人员来说,需要把驱动包添加到项目的构建路径,然后使用java.sql包下的接口编程

接口提供统一的操作方式,驱动提供具体的实现


JDBC核心API:

  • DriverManager 管理驱动、创建数据库连接
  • Connection 数据库连接,用来操作数据库
  • Statement 表示SQL语句,用来执行SQL语句
  • PreparedStatement 表示预编译的带占位符的SQL语句
  • ResultSet 查询结果集

加载JDBC驱动:

Java源码中只提供了JDBC的接口API,但是具体的实现是靠不同的数据库厂商.
即,在使用JDBC之前要先加载不同厂商的驱动(具体的实现)
将MYSQL的JDBC驱动mysql-connector-java-*-bin.jar添加到项目的库中。

加载mysql 的 jdbc驱动: Class.forName("com.mysql.jdbc.Driver")

获得和DBMS的连接:Connection conn = DriverManager.getConnection(
"jdbc:mysql://localhost/demo1?seUnicode=true&characterEncoding=UTF8", "root", "root")

注意:不要引用错了,mysql驱动jar包中也有一个同名的Connection 。
第一个参数叫“连接字符串”,用于设置连接到哪台服务器(localhost),哪个数据库(demo1),以及其他配置信息(和数据库的编码一致)。连接字符串的格式由不同DBMS的驱动来规定,具体查看驱动的文档;
第2、3个参数为用户名、密码。

JDBCUtils

package com.jdbc.test;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

public class JdbcUtils
{
    private static final String drivername;
    private static final String dburl;
    private static final String dbusername;
    private static final String dbpassword;

    // 静态代码块,在类第一次使用的时候执行完成static变量赋值
    static
    {
        InputStream inStream = null;
        try
        {
            inStream = JdbcUtils.class.getResourceAsStream("config.properties");

            Properties prop = new Properties();
            prop.load(inStream);
            // 读取配置文件
            drivername = prop.getProperty("drivername");
            dburl = prop.getProperty("dburl");
            dbusername = prop.getProperty("dbusername");
            dbpassword = prop.getProperty("dbpassword");
        } catch (IOException e)// 把IOException转化为RuntimeException
        {
            // static中不能抛出checkedException(非RuntimeException)
            throw new RuntimeException("加载config.properties出错", e);
        } finally
        {
            if (inStream != null)
            {
                try
                {
                    inStream.close();
                } catch (IOException e)
                {
                    //do nothing
                }
            }
        }

        try
        {
            // 加载jdbc驱动.只用加载一次
            // 所以不放到creatConnection中
            Class.forName(drivername);
        } catch (ClassNotFoundException e)
        {
            throw new RuntimeException("加载Mysql JDBC驱动失败", e);
        }

    }

    // 对于不知道怎么处理的异常,就抛出,不要"藏着掖着"
    public static Connection createConnection() throws SQLException
    {
        return DriverManager.getConnection(dburl, dbusername, dbpassword);
    }
    public static int executeUpdate(String sql, Object... parameters) throws SQLException
    {
        Connection conn=null;
        try
        {
            conn=createConnection();
            return executeUpdate(conn,sql,parameters);
        }
        finally
        {
            closeQuietly(conn);
        }
    }

    public static int executeUpdate(Connection conn, String sql, Object... parameters) throws SQLException
    {
        PreparedStatement ps = null;
        try
        {
            ps = conn.prepareStatement(sql);
            for (int i = 0; i < parameters.length; i++)
            {
                // set...都是从1开始的  依次填充sql中的?
                ps.setObject(i + 1, parameters[i]);
            }
            return ps.executeUpdate();
        }

        /*
         * catch(SQLException e) { System.out.println("执行出错"); //如果只是把异常打印出来不算处理
         * //这叫"吃异常".应该合理的告诉调用者错了(抛出) }
         */
        finally
        {
            closeQuietly(ps);
            // conn用完了不要关,也许人家还有用
        }
    }

    public static ResultSet executeQuery(String sql,Object...parameters) throws SQLException
    {

        Connection conn= createConnection();
        return executeQuery(conn,sql,parameters);

    }
    public static ResultSet executeQuery(Connection conn,String sql,
            Object... parameters)throws SQLException
    {
        //[注意] 这里不要关闭ps,或者会导致返回出去的ResultSet失效
        //外部程序调用时候可以关闭ps,关闭方法:通过rs.getStatement() 先拿到rs关联的Statement
        PreparedStatement ps=conn.prepareStatement(sql);
        for(int i=0;i<parameters.length;i++)
        {
            ps.setObject(i+1, parameters[i]);
        }
        return ps.executeQuery();
    }
    //PreparedStatement继承自Statement
    public static void closeQuietly(Statement stmt)
    //public static void closeQuietly(PreparedStatement stmt)
    {
        if (stmt != null)
        {
            try
            {
                stmt.close();
            } catch (SQLException e)
            {
                // do nothing
            }
        }
    }

    /**
     * 关闭ResultSet以及和其关联的Statement
     * @param ResultSet rs 
     */
    public static void closeResultSetAndStatement(ResultSet rs)
    {
        Statement stmt=null;
        try
        {
            stmt = rs.getStatement();
        }catch(SQLException E)
        {
            //do nothing
        }
        finally
        {
            closeQuietly(rs);
            closeQuietly(stmt);
        }
    }
    /**
     * 把Result和其对应的Statement以及Connection都关掉
     * @param rs
     */
    public static void closeAll(ResultSet rs)
    {
        Statement stmt=null;
        Connection conn=null;
        try
        {
            stmt=rs.getStatement();
            conn=stmt.getConnection();

        }
        catch(SQLException e)
        {
            //do nothing
        }
        finally
        {

            //(*)  CachedRowSet:是一个离线结果集,也就是把数据保存到客户端,Connection可以关闭    (简化关闭,但是耗内存)

            closeQuietly(rs);
            closeQuietly(stmt);
            closeQuietly(conn);
        }

    }
    public static void closeQuietly(Connection conn)
    {
        if (conn != null)
        {
            try
            {
                conn.close();
            } catch (SQLException e)
            {
                // do nothing
            }
        }
    }

    public static void closeQuietly(ResultSet resultSet)
    {
        if (resultSet != null)
        {
            try
            {
                resultSet.close();
            } catch (SQLException e)
            {
                // do nothing
            }
        }
    }

    public static void rollback(Connection conn)
    {
        try
        {
            conn.rollback();
        } catch (SQLException e)
        {
            // do nothing
        }
    }
}

SQL注入漏洞

采用sql拼接的方式
1. 容易产生sql注入漏洞(a’ or ‘a’=’a)
2. 执行效率低,每次的拼接结果都将产生一条新的sql语句,需要对其进行词法分析,语法分析等
解决方案:
采用参数化查询安全;效率高(SQL预编译)

目录

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值