Java-Web-JDBC(尊师黑马)

打印 上一主题 下一主题

主题 756|帖子 756|积分 2268

简介

JDBC 是 Java 提供的一种 API,用于毗连和操纵关系性数据库。它为 Java 提供了一种同一的接口,允许开发者通过一套 Java 代码与不同的数据库进行交互。涉及 SPI 机制,由 Java 语言提供一套标准的 JDBC 接口,由各个数据库服务厂商(MySQL、Oracle 等)做具体实现(驱动)。
其优点是可以随意替换底层的数据库,访问数据库的 Java 代码根本不变。
快速入门

起首必要确保 MySQL 已经下载而且启动服务。

  • 创建工程,导入数据库驱动 jar 包


  • 使用 jdbc 实行 sql
    //注册驱动
    Class.forName(“com.mysql.jdbc.Driver”);
    //获取毗连
    String url = “jdbc:mysql://localhost:3306/test”;
    String username = “root”;
    String password = “1234”;
    Connection conn = DriverManager.getConnection(url, username, password);
    //界说sql
    String sql = “update account set money = 1000 where id = 1;”;
    //获取实行sql的对象Statement
    Statement stmt = conn.createStatement();
    //实行sql
    int count = stmt.executeUpdate(sql);
    System.out.println(count > 0 ? “修改成功” : “修改失败”);
    //释放资源
    stmt.close();
    conn.close();
处理查询语句
  1. // 数据库连接参数
  2. String url = "jdbc:mysql://localhost:3306/test";
  3. String username = "your_username";
  4. String password = "your_password";
  5. Connection conn = null;
  6. Statement stmt = null;
  7. ResultSet rs = null;
  8. try {
  9.     // 1. 获取数据库连接
  10.     conn = DriverManager.getConnection(url, username, password);
  11.     // 2. 创建 Statement 对象
  12.     stmt = conn.createStatement();
  13.     // 3. 执行查询语句
  14.     String query = "SELECT * FROM your_table";
  15.     rs = stmt.executeQuery(query);  // 执行查询并返回结果集
  16.     // 4. 处理查询结果
  17.     while (rs.next()) {
  18.         System.out.println("Column 1: " + rs.getString(1));
  19.         System.out.println("Column 2: " + rs.getString(2));
  20.     }
  21. } catch (SQLException e) {
  22.     e.printStackTrace();
  23. } finally {
  24.     try {
  25.         // 5. 关闭资源
  26.         if (rs != null) rs.close();
  27.         if (stmt != null) stmt.close();
  28.         if (conn != null) conn.close();
  29.     } catch (SQLException e) {
  30.         e.printStackTrace();
  31.     }
  32. }
复制代码
API 详解

DriverManager

DriverManager 是用于管理一组数据库驱动的类。它负责选择符合的数据库驱动程序,并建立与数据库的毗连。DriverManager 是 JDBC 毗连池的一部分,它提供了一个简朴的接口来得到数据库毗连。
驱动注册

我们可以查看注册驱动时使用的 Driver 类:

Ctrl B 查看其源码发现,其内部有一个静态代码块中正是调用了 DriverManager 中的注册方法,而这个静态代码块会随着类的加载而加载。

其着实 MySQL 5 的版本之后,可以不显式使用 DeiverManager.register() 方法也能成功注册驱动,即将 Class.forName() 这一行注释掉依然能够运行成功。这是因为 JDBC 4.0 引入了主动加载驱动程序的机制。只要 JDBC 驱动的 JAR 文件存在于类路径中,而且该驱动的 META-INF/services/java.sql.Driver 文件已经设置好,JDBC 驱动就会主动注册到 DriverManager。

获取毗连

通过查看 DriverManager 的源码可以发现其中有一个 getConnection 方法,正是用于获取数据库毗连。

其中必要传入三个参数:


  • String url:毗连路径

    • 语法:jdbc:mysql://IP地点:端口号/数据库名称参数(键值对,多个使用 & 毗连)
    • 示例:jdbc:mysql://localhost:3306/test
    • 本机 3306 端口的url可以简写:jdbc:mysql:///test
    • 可以在后面用 毗连 useSSL=False 表示不使用 SSL 安全套件,避免告诫提示:jdbc:mysql://localhost:3306/testuseSSL=False

  • user:数据库用户名
  • password:数据库暗码
Connection

在 JDBC 中,Connetion 代表了与数据库的毗连。通过 Connection 对象,应用程序可以实行 SQL 查询、更新数据库、管理事务等操纵。
它的功能包罗:

  • 创建 Statement、PreparedStatement 和 CallableStatement 对象以实行 SQL 查询和更新操纵
  • 启动和管理数据库事务
  • 管理数据库毗连的属性(主动提交、隔离级别等)
  • 提供数据库元数据等(数据库版本、支持的功能等)
获取数据库毗连



  • 使用 DriverManager 获取毗连
    Connection conn = DriverManager.getConnection(“jdbc:mysql://localhost:3306/mydb”, “root”, “password”);
  • 使用 DataSource 获取毗连
    DataSource 是一个更机动的毗连池实现,实用于高性能应用。你可以从毗连池中获取毗连。
    DataSource dataSource = new MysqlDataSource();
    dataSource.setURL(“jdbc:mysql://localhost:3306/mydb”);
    dataSource.setUser(“root”);
    dataSource.setPassword(“password”);
    Connection conn = dataSource.getConnection();
Connection 方法

获取实行 SQL 的对象



  • 普通实行 SQL 对象
    Statement stmt = conn.createStatement();
  • 预编译 SQL 的实行 SQL 对象
    用于防止 SQL 注入
    PreparedStatement pstmt = conn.prepareStatement(“SELECT * FROM users WHERE id = ?”);
  • 实行存储过程的对象
    CallableStatement cstmt = CallableStatement prepareCall(sql)
事务方法



  • 主动提交模式
    默认情况下,JDBC 毗连的事务是主动提交的,即每一条 SQL 语句都会立刻提交到数据库,可以通过 setAutoCommit(false) 禁用主动提交,并在事务竣事时手动提交事务。
    conn.setAutoCommit(boolean autoCommit);
  • 提交事务
    conn.commit();
  • 回滚事务
    conn.rollback();
事务管理演示
先摆设好事务管理的代码:
  1. //1. 注册驱动
  2. Class.forName("com.mysql.jdbc.Driver");
  3. //2. 获取连接
  4. String url = "jdbc:mysql:///test?useSSL=false";
  5. String username = "root";
  6. String password = "1234";
  7. Connection conn = DriverManager.getConnection(url, username, password);
  8. //3. 定义sql
  9. String sql1 = "update account set money = 3000 where id = 1";
  10. String sql2 = "update account set money = 3000 where id = 2";
  11. //4. 获取执行sql的对象 Statement
  12. Statement stmt = conn.createStatement();
  13. //开启事务
  14. conn.setAutoCommit(false);
  15. try {
  16.     //5. 执行sql
  17.     int count1 = stmt.executeUpdate(sql1);//受影响的行数
  18.     //6. 处理结果
  19.     System.out.println(count1 > 0 ? "修改成功" : "修改失败");
  20.     //5. 执行sql
  21.     int count2 = stmt.executeUpdate(sql2);//受影响的行数
  22.     //6. 处理结果
  23.     System.out.println(count2 > 0 ? "修改成功" : "修改失败");
  24. } catch (Exception e) {
  25.     //回滚事务
  26.     conn.rollback();
  27.     System.out.println("出错已回滚");
  28.     e.printStackTrace();
  29. }
  30. //提交事务
  31. conn.commit();
  32. //7.释放资源
  33. stmt.close();
  34. conn.close();
复制代码
此时程序是没有非常的,我们来看实行结果:

如今,在 sql1 的实行结果后面加上一条非常语句:

此时可以看到,IDEA 已经主动将 sql2 的处理语句变灰,提示不会实行下面代码,来看实行结果:

果然,在抛出非常的同时,事务进行了回滚。回滚之后,由于事务的原子性,此时 sql1 对数据库的修改也是不成功的。
Statement

Statement 是 JDBC 中用于实行 SQL 查询、更新和其他数据库操纵的接口。它用于向数据库发送 SQL 语句,并吸收数据库返回的结果。Statement 是 JDBC 最根本的接口之一,通常用于实行简朴的 SQL 语句。
常见方法



  • executeQuery(String sql)
    用于实行 SELECT 查询,并返回一个 ResultSet 对象,ResultSet 存储了查询结果。
    String sql = “SELECT * FROM employees”;
    ResultSet res = stmt.executeQuery(sql);
  • executeUpdate(String sql)
    用于实行 SQL 更新(如 INSERT、UPDATE、DELETE),返回受影响的行数。
    String sql = “UPDATE employees SET salary = 50000 WHERE id = 1”;
    int rowsAffected = stmt.executeUpdate(sql);
  • execute(String sql)
    用于实行任何 SQL 语句。返回一个 boolean 值,表示结果是否为 ResultSet(如果是查询语句则返回 true,否则返回 false)。
    String sql = “DROP TABLE employees”;
    boolean isResultSet = stmt.execute(sql);
  • getGeneratedKeys()
    在实行插入操纵时,如果数据库支持生成主动主键,可以通过这个方法获取插入操纵生成的主键。
    String sql = “INSERT INTO employees (name, age) VALUES (‘John’, 30)”;
    int rowsInserted = stmt.executeUpdate(sql, Statement.RETURN_GENERATED_KEYS);
    ResultSet rs = stmt.getGeneratedKeys();
    if (rs.next()) {
    int generatedId = rs.getInt(1);
    System.out.println("Generated ID: " + generatedId);
    }
常见实现

Statement

用于实行没有参数的静态 SQL 查询。每次实行时都会重新编译 SQL 语句,因此效率较低,尤其是在必要重复实行雷同 SQL 时。
  1. Statement stmt = conn.createStatement();
  2. ResultSet rs = stmt.executeQuery("SELECT * FROM employees");
复制代码
PreparedStatement

用于实行带有参数的预编译 SQL 语句。相比 Statement,它进步了实行效率并避免了 SQL 注入攻击。
  1. String sql = "SELECT * FROM employees WHERE id = ?";
  2. PreparedStatement pstmt = conn.prepareStatement(sql);
  3. pstmt.setInt(1, 1); // 设置参数
  4. ResultSet rs = pstmt.executeQuery();
复制代码
CallableStatement

用于调用存储过程。
  1. String sql = "{call getEmployeeDetails(?)}"; // 存储过程调用
  2. CallableStatement cstmt = conn.prepareCall(sql);
  3. cstmt.setInt(1, 1); // 设置存储过程参数
  4. ResultSet rs = cstmt.executeQuery();
复制代码
ResultSet

在 JDBC 中,ResultSet 是用于表示查询结果的数据布局,它存储从数据库查询返回的数据,并提供方法来访问和处理这些数据。
方法



  • boolean() next
    将光标从当前位置向前移动一行;判定当前行是否为有效行。
    返回 true:有效行,当前行有数据;返回 false:无效行,当前行没有数据。
  • xxx getxxx(参数)
    xxx 表示数据范例,参数有 int 或 String,int 表示列的编号,从 1 开始;String 代表列的名称。
示例

  1. //1. 注册驱动
  2. Class.forName("com.mysql.jdbc.Driver");
  3. //2. 获取连接
  4. String url = "jdbc:mysql:///test?useSSL=false";
  5. String username = "root";
  6. String password = "1234";
  7. Connection conn = DriverManager.getConnection(url, username, password);
  8. //3. 定义sql
  9. String sql = "select * from account";
  10. //4. 获取执行sql的对象 Statement
  11. Statement stmt = conn.createStatement();
  12. //5.执行sql
  13. ResultSet resultSet = stmt.executeQuery(sql);
  14. //6. 处理结果
  15. while(resultSet.next()){
  16.     int id = resultSet.getInt("id");
  17.     String name = resultSet.getString("name");
  18.     int money = resultSet.getInt("money");
  19.     System.out.println(id + " " + name + " " + money);
  20. }
复制代码
查询结果

PreparedStatement

PreparedStatement 是 JDBC 中用于实行预编译 SQL 查询的接口,它相较于 Statement 更高效、安全。通过 PreparedStatement,SQL 查询在实行前被编译,而且可以多次实行,得当重复实行传入不同参数的雷同的 SQL。
使用



  • 获取 PreparedStatement 对象
    // SQL语句中的参数值,使用?占位符替代
    String sql = “SELECT * FROM users WHERE username = ? AND password = ?”;
    // 通过Connection对象获取,并传入对应的sql语句
    PreparedStatement pstmt = conn.prepareStatement(sql);
  • 设置参数值
    Sql 语句使用 ?作为占位符,在实行 SQL 之前必要调用方法设置这些参数值。使用 setXXX(int parameterIndex, XXX x) 给 赋值。
    pstmt.setString(1, “root”); //设置第一个参数为String root
    pstmt.setString(2, “1234”); //设置第二个参数为String 1234
  • 实行 SQL
    executeUpdate() 实行DDL语句和DML语句;executeQuery() 实行DQL语句。
    不必要传递 SQL 语句,因为获取实行对象的时候就已经对语句进行预编译了。
SQL 注入

SQL 注入发生在应用程序没有正确处理用户输入的情况下,攻击者通过注入恶意的 SQL 语句来干扰数据库的正常实行逻辑。通常,注入点存在于拼接 SQL 查询字符串的地方。
假设有一条 sql:
  1. String sql = "SELECT * FROM users WHERE username = '" + username + "' AND password = '" + password + "'";
复制代码
如果用户输入:username = admin 和 password = ' OR '1' = '1,那么生成的 SQL 查询将酿成:
  1. SELECT * FROM users WHERE username = 'admin' AND password = '' OR '1' = '1'
复制代码
该查询总是返回结果,因为 ‘1’ = ‘1’ 总为真,攻击者通过这种方式绕过了暗码验证。
预编译防止 SQL 注入

PreparedStatement 的一个关键特性是 SQL 查询在实行之前会被预编译,而且用户输入的参数(如用户名、暗码等)不会直接拼接进查询字符串中,而是通过参数占位符 传递给数据库。数据库引擎会将这些占位符与传入的参数分别处理,避免了直接在查询中插入用户提供的恶意 SQL 代码。
防止 SQL 注入的重点在于实行之前的编译以及 占位符,对应的参数值会根据其数据范例安全地传递到数据库,不会被当作 SQL 代码实行。
数据库毗连池

数据库毗连池是一种能够复用毗连来进步数据库访问效率的技能,可以看作是一个容器,负责分配、管理数据库毗连。它通过创建一组数据库毗连并在多个请求之间共享这些毗连,避免了频仍的建立和关闭数据库毗连所带来的性能开销。

工作原理

数据库毗连池的根本思想是事先创建一定数量的数据库毗连,将这些毗连保存在池中。当应用程序必要访问数据库时,它从毗连池中获取一个毗连,实行完操纵后,将毗连返回毗连池,而不是直接关闭毗连。这样,下次必要数据库毗连时,应用程序可以直接从池中获取,而不必要重新建立毗连。
如果新请求到来时毗连池毗连已经用完怎么办?


  • 等待(Blocking)
    常见计谋是阻塞等待,即当毗连池中没有空闲毗连时,新的请求会被阻塞,直到有可用毗连为止。毗连池会等待,直到某个毗连被归还到池中。如果设置了最大等待时间,则在等待超时后,新的请求将会失败。
  • 拒绝(Failing)
    当毗连池中没有可用毗连时,新的数据库请求会直接失败,通常会抛出非常。这种方式实用于对于并发请求要求严酷的系统,拒绝额外请求可以避免数据库过载。
  • 扩容(Dunamic Sizing)
    一些毗连池支持动态扩展,即当毗连池中的毗连用完时,毗连池会主动增长新的毗连,直到达到设置的最大毗连数。
  • 其他计谋
    一些毗连池实现提供了更为复杂的设置选项,如等待队列、毗连重试等。
毗连实现

DataSource 是 sun 公司提供的数据库毗连池标准接口,由第三方来实现次接口。
常见的数据库毗连池:


  • Apache DBCP:Apache 提供的数据库毗连池实现,简朴且广泛使用。
  • C3P0:提供了一些更为高级的毗连池特性,如主动测试毗连、毗连池大小主动调整等。
  • HikariCP:一个高性能的 JDBC 毗连池,被广泛认为是当前最良好的毗连池实现之一,特殊是在性能方面。
  • Druid:阿里巴巴开源的数据库毗连池项目,功能强盛,性能良好,是Java语言最好的数据库毗连池之一。
Druid 演示


  • 导入 Druid 驱动


  • 界说设置文件
    先在 src 包下 new 一个 properties 文件:


    添加设置信息:
    注意核对本身的用户名、暗码和数据库名称

  • 创建毗连池
    文件路径填本身创建的 properties 文件路径
    //加载设置文件
    Properties prop = new Properties();
    prop.load(new FileInputStream(“D:\Data\code\IDEA\JavaWeb\JDBC\src\druid.properties”));
    //获取毗连池对象
    DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
  • 获取数据库毗连
    //获取数据库毗连
    Connection conn = dataSource.getConnection();
    //验证
    System.out.println(conn);

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

守听

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表