天天看点

JDBC详解 - Java

JDBC常用接口

  • Statement接口
  1. 用于执行静态SQl语句并返回它所生成结果的对象
  2. 三种Statement类:
  • Statement: 由createStatement创建,用于发送简单的SQL语句(不带参数的)
  1. boolean execute(String sql) : 可以执行任意的sql
  2. int ​

    ​executeUpdate​

    ​(String sql) : 执行DML(insert, update, delete)语句,DDL(create,alter,drop)语句
  3. ResultSet ​

    ​executeQuery​

    ​(String sql) : 执行DQL(select)语句
  • PreparedStatement: 由prepareStatement创建,用于发送含有一个或多个输入参数的sql语句.并且效率更高,还可以防止sql注入.
  • CallableStatement: 继承自PreparedStatement. 由方法prepareCall创建,用于调用存储过程.
  1. 常用的Statement方法:
  • execute(): 运行语句,返回是否有结果集
  • executeQuery(): 运行select语句,返回ResultSet结果集
  • executeUpdate(): 运行insert/update/delete操作,返回更新的行数
  • ResultSet接口
返回结果集对象, 封装查询结果
  1. Statement执行SQL语句时返回ResultSet结果集
  2. ResultSet提供的检索不同类型字段的方法,常用的有:

    next() : 游标向下移动一行

    getXXX(参数) : 获取数据

    - getString(): 获得在数据库中是varchar、char等数据类型的对象

    - getFloat(): 获得在数据库中是Float类型的对象

    - getDate(): 获得在数据库中是Date类型的数据

    - getBoolean(): 获得在数据库中是Boolean类型的数据

    参数 :

    1. int : 代表查询列的编号, 从1开始

    2. String : 代表查询列的名称. 如 : getInt(“stu_password”)

// 循环判断游标是否是最后一行末尾
 while (rs.next()) {
    // 获取数据
    int id = rs.getInt(1);
    String name = rs.getString("stu_username");
 }      
  • PreparedStatement : 执行sql 的对象
  1. SQL注入问题 : 在拼接sql时, 有一些sql 的特殊关键字参与字符串的拼接, 会造成安全性问题
  1. 输入用户这样输入密码 : adf’ or ‘a’ = 'a
  2. sql : ​

    ​select * from user where username='asdflk' and password = 'adf' or 'a' = 'a'​

    ​ 这样的sql拼接导致返回为 true
  1. 解决sql注入问题 : 使用PreparedStatement对象来解决
  2. 预编译的sql : 参数作用 ? 作为占位符 (Statement中是静态sql)
  3. 步骤 :
  1. 导入驱动jar包
  2. 注册驱动 Class.forName(“com.mysql.jdbc.Driver”);
  3. 获取数据库连接对象 Connection
  4. 定义sql
注意 : sql的参数使用 ? 作为占位符. 如 : ​

​select * from user where username = ? and password = ?;​

  1. 获取执行sql语句的对象 PreparedStatement Connection.prepareStatement(String sql)
  2. 给 ? 赋值 :

方法 : setXXX(参数1, 参数2)

- 参数1 : ? 的位置编号, 从1开始

- 参数2 : ? 的值

  1. 执行sql, 接收返回结果, 不需要传递sql语句 ​

    ​rs = ps.executeQuery();​

  2. 处理结果
  3. 释放资源
  • 依次关闭使用对象及连接:

    ResultSet -> Statement -> Connection

包名

domain : 存放实体类, 用来封装数据

util : 存放工具类, 将公共方法抽取到工具类中

JDBC控制事务

  1. 事务 : 一个包含多个步骤的业务操作. 如果这个业务操作被事务管理, 则这多个步骤要么同时成功, 要么同时失败
  2. 使用Connection对象来管理事务
  • 开启事务 : setAutoCommit(boolean autoCommit) : 调用该方法设置参数为false, 即开启事务
  • 在执行sql之前开启事务
  • 提交事务 : commit()
  • 当所有sql都执行完提交事务
  • 回滚事务 : rollback()
  • 在catch中回滚事务

JDBC工具类

放在src目录下的jdbc.properties文件内容

url=jdbc:mysql://localhost:3306/db1
user=root
password=root
driver=com.mysql.jdbc.Driver      
import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.net.URLDecoder;
import java.sql.*;
import java.util.Properties;


/**
 * JDBC工具类
 */
public class JDBCUtils {
    private static String url;
    private static String user;
    private static String password;
    private static String driver;

    /**
     * 文件的读取, 只需要读取一次即可拿到这些值, 使用静态代码块
     */
    static {
        try {
            // 读取资源文件, 获取值
            // 1. 创建Properties集合类
            Properties pro = new Properties();

            // 获取jdbc路径下的文件的方式 --> ClassLoader类加载器
            ClassLoader classLoader = JDBCUtils.class.getClassLoader();
            // 此处的jdbc.properties配置文件需要放在src路径下
            URL res = classLoader.getResource("jdbc.properties");
            String path = res.getPath();
            // 解决路径乱码问题
            String decode = URLDecoder.decode(path, "UTF-8");
            // 2. 加载文件
            pro.load(new FileReader(path));

            // 3. 获取数据, 赋值
            url = pro.getProperty("url");
            user = pro.getProperty("user");
            password = pro.getProperty("password");
            driver = pro.getProperty("driver");
            // 4. 注册驱动
            Class.forName(driver);

        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取连接
     */
    public static Connection getConnection() throws SQLException {
            return DriverManager.getConnection(url, user, password);
    }

    /**
     * 释放资源
     */
    public static void close(ResultSet rs, Statement stmt, Connection conn) {
        // 防止空指针异常
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (stmt != null) {
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    public static void close(Statement stmt, Connection conn) {
        if (stmt != null) {
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printstacktrace();
            }
        }
    }
}      
public static void judgeLogin(String username, String password) {

        if (username == null || password == null) {
            return;
        }

        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            conn = JDBCUtils.getConnection();
            
            // 开启事务
            conn.setAutoCommit(false);
            
            PreparedStatement ps = conn.prepareStatement("select * from user where username= ? and password= ?");
            ps.setObject(1, username);
            ps.setObject(2, password);

            rs = ps.executeQuery();

            // 提交事务
            conn.commit();

            int id = 0;
            if (rs.next()) {
                id = rs.getInt("id");
                System.out.println(id);
            }
            if (id > 0) {
                System.out.println("登录成功");
            } else {
                System.out.println("登录失败");
            }
        } catch (Exception e) {
            // 回滚事务
            try {
                if (conn != null) {
                    conn.rollback();
                }
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
            e.printStackTrace();
        } finally {
            JDBCUtils.close(rs, stmt, conn);
        }
    }