0
点赞
收藏
分享

微信扫一扫

JDBC的六步连接、事务及封装

萍儿的小确幸 2022-04-29 阅读 94
java

JDBC

添加驱动

根据MySQL的版本添加
在这里插入图片描述

JDBC的六步连接

// 数据库的六步连接
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;

try {
    // 1、注册驱动
    // mysql 8.0以上
    Class.forName("com.mysql.cj.jdbc.Driver");
    // mysql 8.0以下
    //Class.forName("com.mysql.jdbc.Driver");
    // oracle数据库
    //Class.forName("oracle.jdbc.driver.OracleDriver");

    // 2、获取连接
    System.out.println("连接数据库。。。");
    // Oracle数据库连接地址:oracle:jdbc:thin:@localhost:1521:数据库名
    // MySQL数据库连接地址:jdbc:mysql://localhost:3306/数据库名
    conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/数据库名", "root", "数据库密码");

    System.out.println("conn : " + conn);
    // 3、获取数据库操作对象
    stmt = conn.createStatement();

    // 4、执行sql语句
    String sql = "sql语句";

    rs = stmt.executeQuery(sql);

    // 5、处理结果集——循环遍历
    // for——我已经知道循环的次数
    // while——不知道循环的次数
    while (rs.next()) {
        // 通过字段检索
        // 例如:int id = rs.getInt("id");
        //      String name = rs.getString("name"); // 不管数据库中是什么类型,统一以String形式返回
        // 输出数据
        // 例如:System.out.println(id + "," + name);
    }

} catch (Exception e) {
    e.printStackTrace();
} finally {
    // 6、释放资源
    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();
        }
    }
}

JDBC的六步连接(使用配置文件的方式)

db.properties

# mysql连接信息
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/数据库名
user=root
password=数据库密码

# oracle连接信息
#driver=oracle.jdbc.driver.OracleDriver
#url=oracle:jdbc:thin:@localhost:1521:数据库名
#user=数据库用户名
#password=数据库密码
// 资源绑定器
ResourceBundle bundle = ResourceBundle.getBundle("resources/db");
// 通过属性配置文件拿到信息
String driver = bundle.getString("driver");
String url = bundle.getString("url");
String user = bundle.getString("user");
String password = bundle.getString("password");

// 数据库的六步连接
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;

try {
    // 1、注册驱动
    Class.forName(driver);

    // 2、获取连接
    System.out.println("连接数据库。。。");
    conn = DriverManager.getConnection(url, user, password);

    System.out.println("conn : " + conn);
    // 3、获取数据库操作对象
    stmt = conn.createStatement();

    // 4、执行sql语句
    String sql = "sql语句";

    rs = stmt.executeQuery(sql);

    // 5、处理结果集——循环遍历
    // for——我已经知道循环的次数
    // while——不知道循环的次数

} catch (Exception e) {
    e.printStackTrace();
} finally {
    // 6、释放资源
    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();
        }
    }
}

防止sql注入攻击

t_user.sql

DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) DEFAULT NULL,
  `password` varchar(255) DEFAULT NULL,
  `role` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

INSERT INTO `t_user` VALUES ('1', 'admin', '123', '管理员');
INSERT INTO `t_user` VALUES ('2', 'user', '123', '普通用户');

登录注册代码

public class JdbcTest01 {
    public static void main(String[] args) {
        // 初始化界面
        HashMap<String, String> loginInfo = login();

        // 连接数据库验证账号密码
        boolean result = checkNameAndPwd(loginInfo.get("loginName"),loginInfo.get("loginPwd"));
        System.out.println(result ? "登录成功" : "登录失败");
    }

    /**
     * 验证用户名和密码
     * @param loginName 登录名
     * @param loginPwd 密码
     * @return true表示登录成功,false表示登录失败
     */
    private static boolean checkNameAndPwd(String loginName, String loginPwd) {
        boolean result = false;
        // 数据库的六步连接
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;

        try {
            // 1、注册驱动
            Class.forName("com.mysql.cj.jdbc.Driver");

            // 2、获取连接
            System.out.println("连接数据库。。。");
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbctest", "root", "123456");

            System.out.println("conn : " + conn);
            // 3、获取数据库操作对象
            stmt = conn.createStatement();

            // 4、执行sql语句
            String sql = "select * from t_user where username = '" + loginName + "' and password = '" + loginPwd + "'";
            System.out.println(sql);
            rs = stmt.executeQuery(sql);

            // 5、处理结果集
            if (rs.next()) {
                result = true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 6、释放资源
            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();
                }
            }
        }
        return result;
    }

    /**
     * 初始化界面,提供用户输入
     * @return 返回存储登录用户名和密码的集合
     */
    private static HashMap<String, String> login() {
        System.out.println("欢迎使用该系统,请输入用户名和密码进行身份认证");
        Scanner scanner = new Scanner(System.in);
        System.out.print("用户名:");
        String loginName = scanner.next();
        System.out.print("密码:");
        String loginPwd = scanner.next();

        // 将用户名和密码放到Map集合中
        HashMap<String, String> loginInfo = new HashMap<>();
        loginInfo.put("loginName",loginName);
        loginInfo.put("loginPwd",loginPwd);
        // 返回Map
        return loginInfo;
    }
}

正常登录
在这里插入图片描述
sql注入攻击
在这里插入图片描述
导致SQL注入的根本原因:先进行了字符串的拼接,再进行的编译。用户输入的用户名信息以及密码信息中含有sql语句的关键词,这个关键词与底层的sql语句进行“字符串拼接”,导致原sql语句的含义被扭曲。
最主要的原因是:用户提供的信息参与了sql语句的编译。

防止sql注入

// Statement stmt = null;
// 改成
PreparedStatement stmt = null;

// 把第三、四步改为以下代码
// 防止SQL注入
String sql = "select * from t_user where username = ? and password = ?";
// prepareStatement 预编译的数据库操作对象
stmt =  conn.prepareStatement(sql);
stmt.setString(1,loginName);
stmt.setString(2,loginPwd);
rs = stmt.executeQuery();

sql注入失败
在这里插入图片描述
java.sql.Statement接口的特点:先进行字符串的拼接,然后再进行sql语句的编译。

  • 优点:使用Statement可以进行sql语句的拼接。
  • 缺点,因为拼接的存在,导致了sql注入。
    java.sql.PreparedStatement接口的特点:先进行sql语句的编译,然后再进行sql语句的传值。
  • 优点:防止了sql注入。
  • 缺点:无法进行sql语句的拼接,只能传值。

模糊查询

要把整个条件当作一个问号

String sql = "select * from t_user where username like ?";
stmt =  conn.prepareStatement(sql);
stmt.setString(1,"%u%");

rs = stmt.executeQuery();

JDBC事务

conn.setAutoCommit(false); // 关闭自动提交机制
conn.commit(); // 手动提交
conn.rollback(); // 手动回滚

DROP TABLE IF EXISTS `t_act`;
CREATE TABLE `t_act` (
  `actno` char(1) PRIMARY KEY,
  `balance` double(10,2)
);

INSERT INTO `t_act` VALUES ('A', '20000.00');
INSERT INTO `t_act` VALUES ('B', '0.00');
/*
JDBC事务:
    conn.setAutoCommit(false);  // 关闭自动提交机制
    conn.commit();  // 手动提交
    conn.rollback();// 手动回滚
 */
public class JdbcTest02 {
    public static void main(String[] args) {
        // 数据库的六步连接
        Connection conn = null;
        PreparedStatement ps = null;

        try {
            // 1、注册驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            // 2、获取连接
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbctest", "root", "123456");

            // 开启事务,关闭自动提交机制
            conn.setAutoCommit(false);

            // 3、获取预编译的数据库操作对象
            String sql = "update t_act set balance = ? where actno = ?";
            ps = conn.prepareStatement(sql);

            ps.setDouble(1,10000);
            ps.setString(2,"A");
            int count = ps.executeUpdate();

            // 模拟异常
            String s = null;
            s.toString();

            ps.setDouble(1,10000);
            ps.setString(2,"B");
            count += ps.executeUpdate();

            System.out.println(count == 2 ? "转账成功" : "转账失败");

            // 手动提交,事务结束
            conn.commit();

        } catch (Exception e) {
            try {
                // 出现异常,手动回滚
                if (conn != null)  conn.rollback();
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
            e.printStackTrace();
        } finally {
            // 6、释放资源
            if (ps != null) {
                try {
                    ps.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

JDBC工具类封装

JDBC工具类:

/*
JDBC工具类
 */
public class DBUtil {
    // 工具类中的构造方法一般都是私有化的,为了防止new对象
    // 工具类中的方法都是静态的,不需要new对象,直接使用“类名.”的方式调用
    private DBUtil() {}

    // 静态变量与静态代码块执行时间一致
    // 类加载时绑定属性资源文件
    private  static ResourceBundle bundle = ResourceBundle.getBundle("resources/db");

    // 注册驱动
    static {
        try {
            Class.forName(bundle.getString("driver"));
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    public static Connection getConnection() throws SQLException {
        String url = bundle.getString("url");
        String user = bundle.getString("user");
        String password = bundle.getString("password");
        Connection conn = DriverManager.getConnection(url, user, password);
        return conn;
    }

    /**
     * 释放资源
     * @param conn 连接对象
     * @param stmt 数据库操作对象
     * @param rs 查询结果集
     */
    public static void close(Connection conn, Statement stmt, ResultSet rs) {
        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();
            }
        }
    }
}

测试DBUtil工具类:

/*
测试DBUtil工具类
 */
public class JdbcTest03 {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            // 获取连接
            conn = DBUtil.getConnection();
            // 获取预编译的数据库操作对象
            String sql = "select * from t_user where username like ?";
            ps = conn.prepareStatement(sql);
            ps.setString(1,"a%");
            // 执行sql
            rs = ps.executeQuery();
            // 处理结果集
            while (rs.next()) {
                System.out.println(rs.getString("username") + "," + rs.getString("password"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 释放资源,没有的对象传null
            DBUtil.close(conn, ps, rs);
        }
    }
}
举报

相关推荐

0 条评论