本文最后更新于:4 个月前

package utils;

import java.sql.*;

/**
 * @Classname JdbcUtils
 * @Description JDBC的工具类。(尽量用单例模式)
 * @Created by melodyjerry
 */
public class JdbcUtil {
    private static final String driverName = "com.mysql.jdbc.Driver";
    // 数据库连接路径
    private static final String URL = "jdbc:mysql://localhost:3306/librarysystem?"   //127.0.0.1
            + "useUnicode = true & serverTimezone = GMT"
            // MySQL在高版本需要指明是否进行SSL连接
            + "& characterEncoding = utf8 & useSSL = false";
    private static final String userName = "root";
    private static final String userPassword = "root";

    private static Connection dbConn = null;
    private static Statement stmt;

    private static JdbcUtil utils = null;
    // 预编译语句
    private static PreparedStatement pstmt = null;

    /**
     * 不是线程安全的
     * 如果有并发访问实例化的时候会出现线程安全的问题
     * 解决办法加同步锁synchronized
     */
    public synchronized static JdbcUtil getJdbcUtil() {
        if (utils == null) {
            utils = new JdbcUtil();
            return utils;
        }
        return utils;
    }

    /**
     * 静态代码块
     * 将加载驱动、连接数据库放入静态块中
     */
    static {
        if (dbConn == null) {
            try
            {
                // 使用Class.forName()方式来加载数据库的驱动类
                // Class.forName()是Java提供的一种基于反射的方式,直接根据类的全限定名(包+类)
                Class.forName(driverName);
                System.out.println("加载驱动成功!");
            }catch(Exception e){
                e.printStackTrace();
                System.out.println("加载驱动失败!");
            }
            try{
                dbConn= DriverManager.getConnection(URL,userName,userPassword);
                System.out.println("连接数据库成功!");
            }catch(Exception e)
            {
                e.printStackTrace();
                System.out.print("SQL Server连接失败!");
            }
        }
    }

    /**
     * 对外提供一个方法来获取数据库连接
     * @return dbConn
     * @throws Exception
     */
    public static Connection getConn() throws Exception {
        return dbConn;
    }

    /**
     * 创建语句对象
     * @return stmt
     * @throws Exception
     */
    public static Statement getStmt() throws Exception {
        if(stmt == null) {
            try {
                if(dbConn == null) {
                    dbConn = getConn();
                }
                stmt = dbConn.createStatement();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return stmt;
    }

    /**
     * 预编译语句对象
     * PreparedStatement对象可以防止sql注入,而Statement不能防止sql注入
     * @param sql
     * @return
     * @throws Exception
     */
    public static PreparedStatement getPstmt(String sql) throws Exception {
        if(pstmt == null) {
            try {
                pstmt = dbConn.prepareStatement(sql);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return pstmt;
    }

    /**
     * 关闭数据库连接
     * @param dbConn
     * @throws Exception
     */
    public void closeConn(Connection dbConn) throws Exception {
        try {
            if(dbConn != null)
                dbConn.close();
        } catch (SQLException e) {
            e.printStackTrace();
            System.out.print("MySQL数据库关闭失败!");
        }
    }

    /**
     * 测试数据库连接、sql操作
     * @param args
     */
    public static void main(String[] args) {
        // 创建实例来测试连接
        JdbcUtil jdbcUtil = new JdbcUtil();
        try {
            getConn(); // jdbcUtil.getConn();

            // 基于数据库连接Connection对象,创建SQL语句执行句柄,Statement对象
            // prepareStatement对象,就是用来基于底层的Connection代表的数据库连接
            // 允许我们通过java程序,通过prepareStatement对象,向MySQL数据库发送SQL语句
            // 从而实现通过发送的SQL语句来执行增删改查等逻辑

            // 第一个,SQL语句中,值所在的地方,都用问号(?)代表
            String sql = "select * from admin where adminName = ? and adminPassword = ?;";
            pstmt = dbConn.prepareStatement(sql);

            // 第二个,必须调用PreparedStatement的setX()系列方法,对指定的占位符设置实际的值
            pstmt.setString(1,"admin");
            pstmt.setString(2,"admin");
            // Statement.executeQuery()方法,用来执行select语句
            // Statement.executeUpdate()方法,就可以用来执行insert、update、delete语句
            // executeUpdate()方法,返回类型是个int值,也就是SQL语句影响的行数

            // 第三个,执行SQL语句时,直接使用executeQuery()即可,不用传入任何参数
            ResultSet rs = pstmt.executeQuery();

//            int rsn = pstmt.executeUpdate();
//            System.out.println("SQL语句影响了【" + rsn + "】行。");

            while(rs.next()){
                //打印的就是总记录数。把检索结果看成只有一跳记录一个字段的表
                System.out.println(rs.getString(3)+"\t");
            }
        } catch (SQLException e) {
            e.printStackTrace();
            System.out.println("sql语句操作失败!"+e.toString());
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("存在异常!"+e.toString());
        }finally {
            try {
                // 最后一定要记得在finally代码块中,尽快在执行完SQL语句之后,就释放数据库连接
                if (pstmt != null){
                    pstmt.close();
                }
                if (dbConn !=null){
                    dbConn.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

}

参考资料:


 目录