5.JavaWeb& 深入浅出JDBC编程

导语:

    JDBC是Java数据库连接的缩写,是Java访问数据库的标准规范。它定义了Java访问数据库的接口和类,而具体的实现由数据库厂商提供。通过使用JDBC,我们可以使用同一套Java代码访问不同的数据库,只需要替换不同的数据库驱动即可。本文将深入浅出地介绍JDBC编程的相关知识。

一、JDBC入门

1.1 JDBC概念

    JDBC规范定义了Java访问数据库的接口和类,具体的实现由数据库厂商提供。因此,我们只需要调用JDBC接口中的方法,而无需关注类是如何实现的。

1.2 使用JDBC开发的包

    在JDBC开发中,我们会使用到java.sql和javax.sql两个包,分别提供与数据库访问相关的接口和类,以及数据库的额外功能。

1.3 JDBC核心API

    JDBC的核心API包括DriverManager、Connection、Statement、PreparedStatement和ResultSet等,分别用于管理数据库驱动、建立数据库连接、执行SQL语句、预编译SQL语句以及封装查询结果集。

1.4 导入驱动Jar包

    在JDBC开发中,导入JDBC驱动包通常可以通过以下几种方式:

  1. 手动导入JAR包:

    • 下载mysql-connector-java-x.x.x.jar,然后将其添加到项目的lib目录中。

    • 在项目属性中设置构建路径,将lib目录添加到类路径中。

  2. 使用构建工具自动导入:

2.1 对于Maven项目,在pom.xml文件中添加依赖

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.26</version>
</dependency>

2.2 对于Gradle项目,在build.gradle文件中添加依赖:


dependencies {
    implementation 'mysql:mysql-connector-java:8.0.26'
}

3. 在线仓库导入:

         在IDE中,通常可以在线添加仓库并导入JAR包,例如在Eclipse中可以通过“Add External JARs”添加mysql-connector-java-x.x.x.jar。

    通过以上方式,我们可以将JDBC驱动包导入到项目中,以便调用JDBC API进行数据库操作。此外,一旦驱动包被添加到项目的类路径中,我们就可以在代码中加载和注册驱动了。

1.5 加载和注册驱动

    在访问数据库之前,我们需要加载并注册数据库驱动。通常可以通过调用Class.forName()方法来实现。例如,对于MySQL数据库,可以这样加载和注册驱动:

// 加载和注册MySQL的JDBC驱动
Class.forName("com.mysql.cj.jdbc.Driver");

// 获取数据库连接
String url = "jdbc:mysql://localhost:3306/数据库名?useSSL=false&serverTimezone=UTC";
Connection conn = DriverManager.getConnection(url, "用户名", "密码");

// 创建Statement对象并执行查询
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM 表名");

// 遍历结果集
while (rs.next()) {
    // 获取列值
    int id = rs.getInt("id");
    String name = rs.getString("name");
    // 输出结果
    System.out.println("id: " + id + ", name: " + name);
}

// 关闭资源
rs.close();
stmt.close();
conn.close();

二、DriverManager类

    DriverManager类是JDBC中用于管理数据库驱动的核心类,主要作用包括:

1.管理和注册数据库驱动:

(1)DriverManager负责管理不同数据库的驱动程序,并通过调用registerDriver()方法来注册数据库驱动。

(2)在加载驱动时,通常会调用Class.forName()方法来动态加载驱动类,这通常会导致驱动类自动注册。

2.创建数据库连接:

(1)DriverManager提供了两种方式来创建数据库连接:

    ①getConnection(String url, String user, String password):通过连接字符串、用户名和密码来获取数据库连接。

    ②getConnection(String url, Properties info):通过连接字符串和属性对象来获取连接,属性对象中包含用户名和密码等信息。

3.获取数据库连接字符串:

(1)DriverManager.getConnection()方法需要传入数据库连接字符串,其格式通常为:jdbc:子协议名称://服务器地址:端口/数据库名?参数名=参数值

(2)例如,对于本地MySQL数据库,连接字符串可以简写为:jdbc:mysql://localhost:3306/数据库名

4.获取连接对象:

(1)一旦连接字符串、用户名和密码提供正确,DriverManager会返回一个Connection对象,用于后续的数据库操作。

    通过以上方法,DriverManager类成为了Java应用程序与数据库之间交互的桥梁,为后续的数据库操作提供了必要的连接资源。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class JdbcDemo {
    public static void main(String[] args) {
        Connection conn = null;
        try {
            // 加载并注册MySQL驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            
            // 使用DriverManager获取数据库连接
            String url = "jdbc:mysql://localhost:3306/testdb";
            String user = "root";
            String password = "root";
            
            // 获取连接
            conn = DriverManager.getConnection(url, user, password);
            
            // 输出连接信息
            System.out.println("获取连接成功:" + conn);
            
        } catch (ClassNotFoundException e) {
            System.out.println("驱动加载失败");
        } catch (SQLException e) {
            System.out.println("获取连接失败");
        } finally {
            if (conn != null) {
                try {
                    // 关闭连接
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

​​​​​​​以上代码实现了以下功能:

  • 加载并注册MySQL驱动。

  • 通过DriverManager获取数据库连接。

  • 输出连接信息。

  • 关闭连接。

    通过以上代码案例,我们可以学习如何使用DriverManager来获取数据库连接,这是进行数据库操作的基础。

三、Connection接口

    Connection接口在JDBC中扮演着至关重要的角色,其主要职责和作用包括:

1.创建Statement和PreparedStatement对象:

(1)通过Connection接口的createStatement()方法可以创建Statement对象,用于执行静态的SQL语句。

(2)通过Connection接口的prepareStatement(String sql)方法可以创建PreparedStatement对象,用于执行预编译的SQL语句。

2.事务处理:

(1)Connection接口提供了事务处理的方法,如setAutoCommit()用于设置自动提交事务模式,commit()用于提交事务,rollback()用于回滚事务。

(2)通过Connection对象可以开启事务,进行一系列的数据库操作,然后选择提交或回滚事务。

3.执行SQL操作:

    Connection接口可以用于执行SQL语句,如通过executeUpdate()执行DML操作,通过executeQuery()执行DQL操作。

4.管理数据库元数据:

    Connection接口提供了获取数据库元数据的方法,如getMetaData()方法,可以获取数据库的元数据信息,如数据库名、表名、列名等。

5.获取数据库连接参数:

    Connection接口可以用于获取数据库连接参数,如通过getCatalog()获取当前数据库的名称,通过getSchema()获取当前schema的名称。

6.设置和获取连接属性:

    Connection接口提供了设置和获取连接属性的方法,如setReadOnly()设置连接是否只读,getReadOnly()获取连接是否只读。

7.管理连接的流:

    Connection接口提供了管理连接的流的方法,如setClientInfo()设置客户端信息,getClientInfo()获取客户端信息。

Connection接口通过封装数据库连接,提供了执行SQL语句、管理事务、获取元数据等核心功能,是JDBC编程中的关键对象。

以下是使用Java和JDBC完成数据库连接、事务处理、执行SQL操作和获取元数据的示例代码:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class ConnectionDemo {

    public static void main(String[] args) {
        Connection conn = null;
        Statement stmt = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;

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

            // 2. 获取连接
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bank", "root", "root");

            // 3. 创建Statement对象
            stmt = conn.createStatement();
            stmt.executeUpdate("insert into account values(null, 'Alice', 1000)");

            // 4. 创建PreparedStatement对象
            pstmt = conn.prepareStatement("select * from account where name = ?");
            pstmt.setString(1, "Alice");
            rs = pstmt.executeQuery();

            // 5. 处理结果集
            while (rs.next()) {
                System.out.println(rs.getString("name") + ", " + rs.getDouble("balance"));
            }

            // 6. 事务处理
            conn.setAutoCommit(false); // 开启事务
            try {
                stmt.executeUpdate("update account set balance = balance - 100 where name = 'Alice'");
                stmt.executeUpdate("update account set balance = balance + 100 where name = 'Bob'");
                conn.commit(); // 提交事务
            } catch (Exception e) {
                conn.rollback(); // 回滚事务
            }

            // 7. 获取数据库元数据
            DatabaseMetaData metaData = conn.getMetaData();
            System.out.println("数据库:" + metaData.getDatabaseProductName());
            System.out.println("驱动版本:" + metaData.getDriverVersion());

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 8. 关闭资源
            try {
                if (rs != null) {
                    rs.close();
                }
                if (stmt != null) {
                    stmt.close();
                }
                if (pstmt != null) {
                    pstmt.close();
                }
                if (conn != null) {
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

​​​​​​​​​​​​​​         这个示例代码实现了使用Java和JDBC完成数据库连接、事务处理、执行SQL操作和获取元数据的核心功能。包括注册驱动、获取连接、创建Statement和PreparedStatement对象、执行SQL操作、事务处理、获取元数据和关闭资源等步骤。

四、Statement接口

   Statement接口在JDBC中扮演着至关重要的角色,其主要职责和作用包括:

  1. 执行SQL语句:通过Connection对象可以创建Statement对象,然后调用其executeUpdate()和executeQuery()方法来执行SQL语句。executeUpdate()方法用于执行DML语句(如insert、update、delete),返回受影响的行数。executeQuery()方法用于执行DQL语句(如select),返回结果集。

  2. 执行DDL语句:Statement接口也可以用于执行DDL语句(如create、alter、drop),这些语句没有返回值,调用executeUpdate()方法执行即可。

  3. 执行带占位符的SQL语句:可以使用预处理语句(PreparedStatement)来实现带占位符的SQL语句。这是Statement接口的一个重要扩展。

  4. 批处理操作:通过addBatch()方法将多条SQL语句添加到批处理中,然后通过executeBatch()方法一次性执行所有添加的SQL语句,从而提高效率。

  5. 关闭Statement对象:在操作完成后,需要关闭Statement对象以释放资源。可以通过调用close()方法来关闭Statement对象。

    以下是一个简单的Java示例代码,演示了如何使用Statement接口执行SQL语句:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

public class StatementDemo {
    public static void main(String[] args) {
        Connection conn = null;
        Statement stmt = null;
        try {
            // 加载驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            
            // 获取连接
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "root");
            
            // 创建Statement对象
            stmt = conn.createStatement();
            
            // 执行SQL语句
            int rows = stmt.executeUpdate("UPDATE users SET username = 'John' WHERE id = 1");
            System.out.println("影响的行数:" + rows);
            
            // 执行查询语句
            ResultSet rs = stmt.executeQuery("SELECT * FROM users");
            while (rs.next()) {
                System.out.println(rs.getString("username"));
            }
            
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        } finally {
            // 关闭资源
            try {
                if (stmt != null) {
                    stmt.close();
                }
                if (conn != null) {
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

​​​​​​​​​​​​​​        在这个示例中,我们首先加载了MySQL的JDBC驱动,然后通过DriverManager获取了数据库连接。接着,我们创建了Statement对象,并使用其executeUpdate()方法执行了一个更新操作,同时获取了受影响的行数。我们还使用executeQuery()方法执行了一个查询操作,并遍历了结果集。最后,我们关闭了Statement对象和数据库连接。

五、数据库工具类JdbcUtils

    为了简化JDBC编程,我们可以编写一个JdbcUtils工具类,其中包含获取数据库连接、关闭资源等方法。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

public class JdbcUtils {

    // 数据库驱动名
    private static final String DRIVER = "com.mysql.cj.jdbc.Driver";

    // 数据库URL
    private static final String URL = "jdbc:mysql://localhost:3306/mydb";

    // 数据库用户名
    private static final String USER = "root";

    // 数据库密码
    private static final String PASSWORD = "root";

    // 注册数据库驱动
    static {
        try {
            Class.forName(DRIVER);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    // 获取数据库连接
    public static Connection getConnection() {
        Connection conn = null;
        try {
            conn = DriverManager.getConnection(URL, USER, PASSWORD);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return conn;
    }

    // 关闭资源
    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();
            }
        }
    }

    // 关闭资源(没有ResultSet的情况)
    public static void close(Connection conn, Statement stmt) {
        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 main(String[] args) {
        Connection conn = JdbcUtils.getConnection();
        Statement stmt = null;
        ResultSet rs = null;
        try {
            stmt = conn.createStatement();
            rs = stmt.executeQuery("SELECT * FROM users");
            while (rs.next()) {
                System.out.println(rs.getString("username"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.close(conn, stmt, rs);
        }
    }
}

​​​​​​​​​​​​​​        这个JdbcUtils工具类实现了获取数据库连接、关闭资源等功能,简化了JDBC编程。其中,通过静态代码块注册了数据库驱动,提供了getConnection()方法来获取数据库连接,并提供了两个close()方法来关闭资源。在main()方法中,我们使用JdbcUtils获取连接并执行了查询操作,最后调用close()方法关闭资源。

六、PreparedStatement接口

    PreparedStatement接口是Statement的子接口,用于执行预编译的SQL语句。相比Statement接口,它具有以下优点:

  1. 防止SQL注入:使用占位符?设置参数,避免了将用户输入直接拼接进SQL语句,从而有效防止SQL注入攻击。

  2. 提高执行效率:预编译的SQL语句可以重复使用,只需改变参数,无需重新编译,从而提高了执行效率。

  3. 提高可读性:使用占位符使SQL语句更加清晰,提高了代码的可读性。

使用PreparedStatement的步骤包括:

  1. 编写SQL语句:使用占位符?代替参数。

  2. 创建PreparedStatement对象:通过Connection对象调用prepareStatement()方法创建。

  3. 设置参数:使用setXxx()方法设置参数。

  4. 执行SQL语句:调用execute()、executeQuery()、executeUpdate()等方法执行SQL语句。

  5. 处理结果:如果是查询,则处理ResultSet结果集。

  6. 关闭资源:关闭ResultSet、PreparedStatement、Connection等资源。

示例代码:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class PreparedStatementExample {

    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "root");
            String sql = "select * from users where id=?";
            pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, 1); // 设置参数
            rs = pstmt.executeQuery();
            while (rs.next()) {
                System.out.println(rs.getString("username"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (rs != null) rs.close();
                if (pstmt != null) pstmt.close();
                if (conn != null) conn.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

​​​​​​​​​​​​​​        这个示例展示了如何使用PreparedStatement进行数据库查询,并通过设置参数避免了SQL注入。同时,该示例还展示了资源的关闭顺序。

七、JDBC事务处理

    JDBC提供了对事务的支持。通过Connection对象的setAutoCommit()、commit()和rollback()方法,可以开启事务、提交事务和回滚事务。事务处理的步骤如下:

  1. 开启事务:调用Connection对象的setAutoCommit(false)方法,关闭自动提交。

  2. 执行操作:执行需要事务管理的SQL语句,通常通过PreparedStatement对象进行操作。

  3. 提交事务:如果操作成功,调用Connection对象的commit()方法提交事务。

  4. 回滚事务:如果操作失败,调用Connection对象的rollback()方法回滚事务。

  5. 关闭资源:最后关闭Connection、PreparedStatement等资源。

示例代码如下:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;

public class TransactionExample {

    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement pstmt1 = null;
        PreparedStatement pstmt2 = null;
        try {
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "root");
            conn.setAutoCommit(false); // 开启事务
            
            pstmt1 = conn.prepareStatement("update account set balance = balance - 100 where id = 1");
            pstmt1.executeUpdate();
            
            // 模拟异常
            int x = 1 / 0;
            
            pstmt2 = conn.prepareStatement("update account set balance = balance + 100 where id = 2");
            pstmt2.executeUpdate();
            
            conn.commit(); // 提交事务
            System.out.println("转账成功");
            
        } catch (Exception e) {
            try {
                if (conn != null) {
                    conn.rollback(); // 回滚事务
                }
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
            System.out.println("转账失败");
            e.printStackTrace();
        } finally {
            // 关闭资源
            try {
                if (pstmt2 != null) pstmt2.close();
                if (pstmt1 != null) pstmt1.close();
                if (conn != null) conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

​​​​​​​​​​​​​​        在这个示例中,我们首先开启事务,然后执行两条更新语句模拟转账操作。如果在执行过程中出现异常,我们回滚事务;如果正常完成,我们提交事务。最后,我们关闭资源。

结语:

    本文详细介绍了JDBC编程的相关知识,包括JDBC概念、核心API、连接数据库、Statement和PreparedStatement的使用,以及JDBC事务处理等内容。掌握这些知识,将有助于我们使用Java进行数据库编程。

欢迎大家后台联系讨论。

(一份Java面试宝典,有兴趣的读者姥爷可以私信我领取!!!免费滴)

图片

  • 50
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值