JDBC的Jar包下载

image.pngimage.png

JDBC基本连接步骤:

**

步骤:

  1. 导入驱动jar包 mysql-connector-java-5.1.37-bin.jar 1.复制mysql-connector-java-5.1.37-bin.jar到项目的libs目录下 2.右键—>Add As Library
    1. 注册驱动
    2. 获取数据库连接对象 Connection
    3. 定义sql
    4. 获取执行sql语句的对象 Statement
    5. 执行sql,接受返回结果
    6. 处理结果
    7. 释放资源
  1. //代码实现:
  2. //1. 导入驱动jar包
  3. //2.注册驱动
  4. Class.forName("com.mysql.jdbc.Driver");
  5. //3.获取数据库连接对象
  6. Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db3", "root", "root");
  7. //4.定义sql语句
  8. String sql = "update account set balance = 500 where id = 1";
  9. //5.获取执行sql的对象 Statement
  10. Statement stmt = conn.createStatement();
  11. //6.执行sql
  12. int count = stmt.executeUpdate(sql);
  13. //7.处理结果
  14. System.out.println(count);
  15. //8.释放资源
  16. stmt.close();
  17. conn.close();

JDBC异常捕捉版本:

  1. //代码:
  2. Statement stmt = null;
  3. Connection conn = null;
  4. try {
  5. //1. 注册驱动
  6. Class.forName("com.mysql.jdbc.Driver");
  7. //2. 定义sql
  8. String sql = "insert into account values(null,'王五',3000)";
  9. //3.获取Connection对象
  10. conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db3", "root", "root");
  11. //4.获取执行sql的对象 Statement
  12. stmt = conn.createStatement();
  13. //5.执行sql
  14. int count = stmt.executeUpdate(sql);//影响的行数
  15. //6.处理结果
  16. System.out.println(count);
  17. if(count > 0){
  18. System.out.println("添加成功!");
  19. }else{
  20. System.out.println("添加失败!");
  21. }
  22. } catch (ClassNotFoundException e) {
  23. e.printStackTrace();
  24. } catch (SQLException e) {
  25. e.printStackTrace();
  26. }finally {
  27. //stmt.close();
  28. //7. 释放资源
  29. //避免空指针异常
  30. if(stmt != null){
  31. try {
  32. stmt.close();
  33. } catch (SQLException e) {
  34. e.printStackTrace();
  35. }
  36. }
  37. if(conn != null){
  38. try {
  39. conn.close();
  40. } catch (SQLException e) {
  41. e.printStackTrace();
  42. }
  43. }
  44. }

通过上列代码可以发现,每当我们需要对DB进行操作时都要经过DB的连接与释放,代码重复率过高

抽取JDBC工具类 : JDBCUtils

目的:简化书写

分析:

  1. 注册驱动也抽取
  2. 抽取一个方法获取连接对象
    • 需求:不想传递参数(麻烦),还得保证工具类的通用性。
    • 解决:配置文件

jdbc.properties 内部配置: url=jdbc:mysql://localhost:3306/db3 user=root password=root driver=com.mysql.jdbc.Driver

  1. /**
  2. * JDBC工具类
  3. */
  4. public class JDBCUtils {
  5. private static String url;
  6. private static String user;
  7. private static String password;
  8. private static String driver;
  9. /**
  10. * 文件的读取,只需要读取一次即可拿到这些值。使用静态代码块
  11. */
  12. static{
  13. //读取资源文件,获取值。
  14. try {
  15. //1. 创建Properties集合类。
  16. Properties pro = new Properties();
  17. //获取src路径下的文件的方式--->ClassLoader 类加载器
  18. ClassLoader classLoader = JDBCUtils.class.getClassLoader();
  19. URL res = classLoader.getResource("jdbc.properties");
  20. String path = res.getPath();
  21. //2. 加载文件
  22. pro.load(new FileReader(path));
  23. //3. 获取数据,赋值
  24. url = pro.getProperty("url");
  25. user = pro.getProperty("user");
  26. password = pro.getProperty("password");
  27. driver = pro.getProperty("driver");
  28. //4. 注册驱动
  29. Class.forName(driver);
  30. } catch (IOException e) {
  31. e.printStackTrace();
  32. } catch (ClassNotFoundException e) {
  33. e.printStackTrace();
  34. }
  35. }
  36. /**
  37. * 获取连接
  38. * @return 连接对象
  39. */
  40. public static Connection getConnection() throws SQLException {
  41. return DriverManager.getConnection(url, user, password);
  42. }
  43. /**
  44. * 释放资源
  45. * @param stmt
  46. * @param conn
  47. */
  48. public static void close(Statement stmt,Connection conn){
  49. if( stmt != null){
  50. try {
  51. stmt.close();
  52. } catch (SQLException e) {
  53. e.printStackTrace();
  54. }
  55. }
  56. if( conn != null){
  57. try {
  58. conn.close();
  59. } catch (SQLException e) {
  60. e.printStackTrace();
  61. }
  62. }
  63. }
  64. /**
  65. * 释放资源
  66. * @param stmt
  67. * @param conn
  68. */
  69. public static void close(ResultSet rs,Statement stmt, Connection conn){
  70. if( rs != null){
  71. try {
  72. rs.close();
  73. } catch (SQLException e) {
  74. e.printStackTrace();
  75. }
  76. }
  77. if( stmt != null){
  78. try {
  79. stmt.close();
  80. } catch (SQLException e) {
  81. e.printStackTrace();
  82. }
  83. }
  84. if( conn != null){
  85. try {
  86. conn.close();
  87. } catch (SQLException e) {
  88. e.printStackTrace();
  89. }
  90. }
  91. }
  92. }

PreparedStatement 介绍

目的:

  • 可以防止SQL注入
  • 效率更高

详解各个对象: **

  1. DriverManager:驱动管理对象

    • 注册驱动:告诉程序该使用哪一个数据库驱动jar
      • 代码使用:Class.forName(“com.mysql.jdbc.Driver”);
      • 注意:mysql5 之后的驱动 jar 包可以省略注册驱动的步骤
    • 获取数据库连接:

      • 方法:

        • static Connection getConnection(String url, String user, String password)
      • 参数:

        1. url:指定连接的路径

          • 语法:jdbc:mysql://ip地址(域名):端口号/数据库名称
          • 例子:jdbc:mysql://localhost:3306/db3 ** ** (db3为数据库名)
          • 细节:本机mysql服务器,且默认端口3306,则url可简写:jdbc:mysql:///db3
        2. user:用户名

        3. password:密码
  1. Connection:数据库连接对象

    • 功能:

      • 获取执行sql 的对象

        • Statement createStatement()
        • PreparedStatement prepareStatement(String sql)
    • 管理事务:

      • 开启事务:setAutoCommit(boolean autoCommit) 设置参数为false,即开启事务
      • 提交事务:commit()
      • 回滚事务:rollback()
  1. Statement:执行 sql 的对象

    • boolean execute (String sql)

      1. - 可以执行任意的sql 了解
    • int executeUpdate(String sql)

      1. - 执行**DML**(insertupdatedelete)语句、**DDL**(createalterdrop)语句
      2. - 返回值:影响的行数,可以通过这个影响的行数判断DML语句是否执行成功
      3. - 返回值>0的则执行成功,反之,则失败。
    • ResultSet executeQuery(String sql)

      1. - 执行**DQL**(select) 语句
  1. ResultSet:结果集对象,封装查询结果

    • 方法:

      • boolean next()

        • 游标向下移动一行,判断当前行是否是最后一行末尾 ( 是否有数据 )

          • 如果是,则返回false,如果不是则返回true
      • getXxx ( 参数 )

        • 获取数据
        • Xxx:代表数据类型 如: int getInt( ) , String getString( )
        • 参数:

          • int: 代表列的编号,从1开始 如: getString(1)
          • String:代表列名称。 如: getDouble(“balance”)

**

  1. PreparedStatement:执行sql的对象

原因:SQL注入问题:在拼接sql时,有一些sql的特殊关键字参与字符串的拼接。会造成安全性问题

  1. 1. 输入用户随便,输入密码:a' or 'a' = 'a
  2. 1. sqlselect * from user where username = 'fhdsjkf' and password = 'a' **or 'a' = 'a' **

**

为解决sql注入问题:使用PreparedStatement对象来解决

预编译的SQL:参数使用 ? 作为占位符

  • 步骤:

    1. 1. 导入驱动jar mysql-connector-java-5.1.37-bin.jar
    2. 1. 注册驱动
    3. 1. 获取数据库连接对象 Connection
    4. 1. 定义sql
    5. - 注意:sql 的参数**使用 ?作为占位符**。
    6. - 如:**select * from user where username = ? and password = ?;**
    7. 5. 获取执行sql语句的对象 PreparedStatement Connection.prepareStatement(String sql)
    8. 5. 给?赋值:
    9. - 方法: setXxx(参数1,参数2)
    10. - 参数1:?的位置编号 1 开始
    11. - 参数2:?的值
    12. 7. 执行sql,接受返回结果,不需要传递sql语句
    13. 7. 处理结果
    14. 7. 释放资源
  • 注意:后期都会使用PreparedStatement来完成增删改查的所有操作

    1. - 可以防止SQL注入
    2. - 效率更高



**

JDBCUtils配合PreparedStatement 的使用

利用 JDBCUtils 工具类极大的简化了代码的重复使用量,以及提高了代码的复用性

  1. public class JDBCDemo {
  2. /**
  3. * 登录方法,使用PreparedStatement实现
  4. */
  5. public boolean login(String username ,String password){
  6. if(username == null || password == null){
  7. return false;
  8. }
  9. //连接数据库判断是否登录成功
  10. Connection conn = null;
  11. PreparedStatement pstmt = null;
  12. ResultSet rs = null;
  13. //1.获取连接
  14. try {
  15. conn = JDBCUtils.getConnection();
  16. //2.定义sql
  17. String sql = "select * from user where username = ? and password = ?";
  18. //3.获取执行sql的对象
  19. pstmt = conn.prepareStatement(sql);
  20. //给?赋值
  21. pstmt.setString(1,username);
  22. pstmt.setString(2,password);
  23. //4.执行查询,不需要传递sql
  24. rs = pstmt.executeQuery();
  25. //5.判断
  26. return rs.next();//如果有下一行,则返回true
  27. } catch (SQLException e) {
  28. e.printStackTrace();
  29. }finally {
  30. JDBCUtils.close(rs,pstmt,conn);
  31. }
  32. return false;
  33. }
  34. }