第三章 JDBC的查询

JDBC的查询操作

ResultSet 是 JDBC (Java 数据库连接) API 提供的接口,它用于表示 SQL 查询的结果集。ResultSet 对象中包含了查询结果的所有行,可以通过 next() 方法逐行地获取并处理每一行的数据。它最常用于执行 SELECT 语句查询出来的结果集。

ResultSet 的遍历是基于 JDBC 的流式处理机制的,即一行一行地获取结果,避免将所有结果全部取出后再进行处理导致内存溢出问题。

在使用 ResultSet 遍历查询结果时,一般会采用以下步骤:

  1. 执行 SQL 查询,获取 ResultSet 对象。
  2. 使用 ResultSet 的 next() 方法移动游标指向结果集的下一行,判断是否有更多的数据行。
  3. 如果有更多的数据行,则使用 ResultSet 对象提供的 getXXX() 方法获取当前行的各个字段(XXX 表示不同的数据类型)。例如,getLong("id") 方法用于获取当前行的 id 列对应的 Long 类型的值。
  4. 处理当前行的数据,例如将其存入 Java 对象中。
  5. 重复执行步骤 2~4,直到结果集中的所有行都被遍历完毕。
  6. 调用 ResultSet 的 close() 方法释放资源。

需要注意的是,在使用完 ResultSet 对象之后,需要及时关闭它,以释放数据库资源并避免潜在的内存泄漏问题。否则,如果在多个线程中打开了多个 ResultSet 对象,并且没有正确关闭它们的话,可能会导致数据库连接过多,从而影响系统的稳定性和性能。

通过列索引获取数据(以String类型获取)

需求:获取t_user表中所有数据,在控制台打印输出每一行的数据。

select id,name,password,realname,gender,tel from t_user;

要查询的数据如下图:

代码如下(重点关注第4步 第5步 第6步):

import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Connection;
import java.sql.Statement;
import java.util.ResourceBundle;
import java.sql.ResultSet;

public class JDBCTest09 {
    public static void main(String[] args){

        // 通过以下代码获取属性文件中的配置信息
        ResourceBundle bundle = ResourceBundle.getBundle("jdbc");
        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. 获取连接
            conn = DriverManager.getConnection(url, user, password);

            // 3. 获取数据库操作对象
            stmt = conn.createStatement();

            // 4. 执行SQL语句
            String sql = "select id,name,password,realname,gender,tel from t_user";
            rs = stmt.executeQuery(sql);

            // 5. 处理查询结果集(这里的处理方式就是:遍历所有数据并输出)
            while(rs.next()){
                String id = rs.getString(1);
                String name = rs.getString(2);
                String pwd = rs.getString(3);
                String realname = rs.getString(4);
                String gender = rs.getString(5);
                String tel = rs.getString(6);
                System.out.println(id + "\t" + name + "\t" + pwd + "\t" + realname + "\t" + gender + "\t" + tel);
            }

        } catch(SQLException | ClassNotFoundException 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();
                }
            }
        }
    }
}
public class JDBCTest03 {
    public static void main(String[] args) {

        // 读取属性配置文件
        ResourceBundle bundle = ResourceBundle.getBundle("com.powernode.jdbc.jdbc");
        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. 获取连接
            conn = DriverManager.getConnection(url, user, password);
            System.out.println(conn);

            // 3.获取数据库操作对象
            stmt = conn.createStatement();

            // 4.执行SQL
            String sql = "select realname,id,name,password from t_user";
            rs = stmt.executeQuery(sql);

            // 5.处理查询结果集
            // 这里的处理方式就是直接打印输出。
            /*
            +----------+----+----------+----------+
            | realname | id | name     | password |
            +----------+----+----------+----------+
            | 张三     |  1 | zhangsan | 123      |
            | 管理员   |  2 | admin    | admin123 |
            +----------+----+----------+----------+
             */
            /*boolean hasNext = rs.next();
            if(hasNext) {
                // 取出光标指向的当前行的数据
                // 不管数据库表中是什么数据类型,统一以字符串的形式取出。
                // 以下的获取方式是通过列下标获取的,列下标从1开始。
                String realname = rs.getString(1);
                String id = rs.getString(2);
                String name = rs.getString(3);
                String pwd = rs.getString(4);
                System.out.println(realname + "\t" + id + "\t" + name + "\t" + pwd);
            }

            hasNext = rs.next();
            if(hasNext) {
                String realname = rs.getString(1);
                String id = rs.getString(2);
                String name = rs.getString(3);
                String pwd = rs.getString(4);
                System.out.println(realname + "\t" + id + "\t" + name + "\t" + pwd);
            }

            hasNext = rs.next();
            System.out.println(hasNext);*/

            while(rs.next()){
                // 取出当前光标指向的这一行的数据。
                String s1 = rs.getString(1);
                String s2 = rs.getString(2);
                String s3 = rs.getString(3);
                String s4 = rs.getString(4);
                System.out.println(s1 + "\t" + s2 + "\t" + s3 + "\t" + s4);
            }

            // 查询所有员工信息
            String sql2 = "select empno,ename,sal from emp";
            rs = stmt.executeQuery(sql2);
            while(rs.next()){
                // 以指定的类型获取数据
                int empno = rs.getInt(1);
                String ename = rs.getString(2);
                double sal = rs.getDouble(3);
                System.out.println(empno + "," + ename + "," + sal * 10);
            }

            System.out.println("==============================");
            // 查询所有员工信息
            String sql3 = "select empno a, ename b, sal c from emp";
            /*
            +------+--------+---------+
            | a    | b      | c       |
            +------+--------+---------+
            | 7369 | SMITH  |  800.00 |
            | 7499 | ALLEN  | 1600.00 |
            | 7521 | WARD   | 1250.00 |
            | 7566 | JONES  | 2975.00 |
            | 7654 | MARTIN | 1250.00 |
            | 7698 | BLAKE  | 2850.00 |
            | 7782 | CLARK  | 2450.00 |
            | 7788 | SCOTT  | 3000.00 |
            | 7839 | KING   | 5000.00 |
            | 7844 | TURNER | 1500.00 |
            | 7876 | ADAMS  | 1100.00 |
            | 7900 | JAMES  |  950.00 |
            | 7902 | FORD   | 3000.00 |
            | 7934 | MILLER | 1300.00 |
            +------+--------+---------+
             */
            rs = stmt.executeQuery(sql3);
            while(rs.next()){
                int empno = rs.getInt("a");
                // 报错,原因:这是因为查询结果集中没有empno这个列。只有a这个列。
                //int empno = rs.getInt("empno");
                String ename = rs.getString("b");
                String sal = rs.getString("c");
                System.out.println(empno + "," + ename + "," + sal);
            }

        } 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();
                }
            }
        }
    }
}

执行结果如下:

代码解读:

// 4. 执行SQL语句
String sql = "select id,name,password,realname,gender,tel from t_user";
rs = stmt.executeQuery(sql);

执行insert delete update语句的时候,调用Statement接口的executeUpdate()方法。执行select语句的时候,调用Statement接口的executeQuery()方法。执行select语句后返回结果集对象:ResultSet。

代码解读:

// 5. 处理查询结果集(这里的处理方式就是:遍历所有数据并输出)
while(rs.next()){
    String id = rs.getString(1);
    String name = rs.getString(2);
    String pwd = rs.getString(3);
    String realname = rs.getString(4);
    String gender = rs.getString(5);
    String tel = rs.getString(6);
    System.out.println(id + "\t" + name + "\t" + pwd + "\t" + realname + "\t" + gender + "\t" + tel);
}
  • rs.next() 将游标移动到下一行,如果移动后指向的这一行有数据则返回true,没有数据则返回false。
  • while循环体当中的代码是处理当前游标指向的这一行的数据。(注意:是处理的一行数据)
  • rs.getString(int columnIndex) 其中 int columnIndex 是查询结果的列下标,列下标从1开始,以1递增。

  • rs.getString(...) 方法在执行时,不管底层数据库中的数据类型是什么,统一以字符串String类型来获取。

代码解读:

// 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();
    }
}

ResultSet最终也是需要关闭的。先关闭ResultSet,再关闭Statement,最后关闭Connection

通过列名获取数据(以String类型获取)

获取当前行的数据,不仅可以通过列下标获取,还可以通过查询结果的列名来获取,通常这种方式是被推荐的,因为可读性好。例如这样的SQL:

select id, name as username, realname from t_user;

执行结果是:

我们可以按照查询结果的列名来获取数据:

注意:是根据查询结果的列名,而不是表中的列名。以上查询的时候将字段name起别名username了,所以要根据username来获取,而不能再根据name来获取了。

import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Connection;
import java.sql.Statement;
import java.util.ResourceBundle;
import java.sql.ResultSet;

public class JDBCTest10 {
    public static void main(String[] args){

        // 通过以下代码获取属性文件中的配置信息
        ResourceBundle bundle = ResourceBundle.getBundle("jdbc");
        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. 获取连接
            conn = DriverManager.getConnection(url, user, password);

            // 3. 获取数据库操作对象
            stmt = conn.createStatement();

            // 4. 执行SQL语句
            String sql = "select id,name as username,realname from t_user";
            rs = stmt.executeQuery(sql);

            // 5. 处理查询结果集(这里的处理方式就是:遍历所有数据并输出)
            while(rs.next()){
                String id = rs.getString("id");
                String name = rs.getString("username");
                String realname = rs.getString("realname");
                System.out.println(id + "\t" + name + "\t" + realname);
            }

        } catch(SQLException | ClassNotFoundException 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();
                }
            }
        }
    }
}

执行结果如下:

如果将上面代码中rs.getString("username")修改为rs.getString("name"),执行就会出现以下错误:

提示name列是不存在的。所以一定是根据查询结果中的列名来获取,而不是表中原始的列名。

以指定的类型获取数据

前面的程序可以看到,不管数据库表中是什么数据类型,都以String类型返回。当然,也能以指定类型返回。使用PowerDesigner再设计一张商品表:t_product,使用Navicat for MySQL工具准备数据如下:

id以long类型获取,name以String类型获取,price以double类型获取,create_time以java.sql.Date类型获取,代码如下:

import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Connection;
import java.sql.Statement;
import java.util.ResourceBundle;
import java.sql.ResultSet;

public class JDBCTest11 {
    public static void main(String[] args){

        // 通过以下代码获取属性文件中的配置信息
        ResourceBundle bundle = ResourceBundle.getBundle("jdbc");
        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. 获取连接
            conn = DriverManager.getConnection(url, user, password);

            // 3. 获取数据库操作对象
            stmt = conn.createStatement();

            // 4. 执行SQL语句
            String sql = "select id,name,price,create_time as createTime from t_product";
            rs = stmt.executeQuery(sql);

            // 5. 处理查询结果集(这里的处理方式就是:遍历所有数据并输出)
            while(rs.next()){
                long id = rs.getLong("id");
                String name = rs.getString("name");
                double price = rs.getDouble("price");
                java.sql.Date createTime = rs.getDate("createTime");
                // 以指定类型获取后是可以直接用的,例如获取到价格后,统一让价格乘以2
                System.out.println(id + "\t" + name + "\t" + price * 2 + "\t" + createTime);
            }

        } catch(SQLException | ClassNotFoundException 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();
                }
            }
        }
    }
}
public class JDBCTest04 {
    public static void main(String[] args) {
        // 读取属性配置文件
        ResourceBundle bundle = ResourceBundle.getBundle("com.powernode.jdbc.jdbc");
        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.获取连接
            conn = DriverManager.getConnection(url, user, password);
            // 3.获取数据库操作对象
            stmt = conn.createStatement();
            // 4.执行SQL语句
            String sql = "select id,name,price,create_time from t_product";
            rs = stmt.executeQuery(sql);
            // 5.处理查询结果集
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
            while(rs.next()){
                // 以特定的类型获取数据
                long id = rs.getLong("id");
                String name = rs.getString("name");
                double price = rs.getDouble("price");
                // 注意:从mysql数据库当中获取的日期类型的数据对应的java类型是:java.sql.Date。不是java.util.Date。
                Date createTime = rs.getDate("create_time");
                System.out.println(id + "," + name + "," + price + "," + createTime);
                // 将java.sql.Date 转换成 java.util.Date(通过构造方法来完成转换。)
                java.util.Date date = new java.util.Date(createTime.getTime());
                // 进行格式化显示
                String strDate = sdf.format(date);
                System.out.println(strDate);
            }
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            // 6.释放资源
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    throw new RuntimeException(e);
                }
            }
            if (stmt != null) {
                try {
                    stmt.close();
                } catch (SQLException e) {
                    throw new RuntimeException(e);
                }
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    throw new RuntimeException(e);
                }
            }
        }

    }
}

执行结果如下:

获取结果集的元数据信息(了解)

ResultSetMetaData 是一个接口,用于描述 ResultSet 中的元数据信息,即查询结果集的结构信息,例如查询结果集中包含了哪些列,每个列的数据类型、长度、标识符等。

ResultSetMetaData 可以通过 ResultSet 接口的 getMetaData() 方法获取,一般在对 ResultSet 进行元数据信息处理时使用。例如,可以使用 ResultSetMetaData 对象获取查询结果中列的信息,如列名、列的类型、列的长度等。通过 ResultSetMetaData 接口的方法,可以实现对查询结果的基本描述信息操作,例如获取查询结果集中有多少列、列的类型、列的标识符等。以下是一段通过 ResultSetMetaData 获取查询结果中列的信息的示例代码:

import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Connection;
import java.sql.Statement;
import java.util.ResourceBundle;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;

public class JDBCTest12 {
    public static void main(String[] args){

        // 通过以下代码获取属性文件中的配置信息
        ResourceBundle bundle = ResourceBundle.getBundle("jdbc");
        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. 获取连接
            conn = DriverManager.getConnection(url, user, password);

            // 3. 获取数据库操作对象
            stmt = conn.createStatement();

            // 4. 执行SQL语句
            String sql = "select id,name,price,create_time as createTime from t_product";
            rs = stmt.executeQuery(sql);

            // 获取元数据信息
            ResultSetMetaData rsmd = rs.getMetaData();
            int columnCount = rsmd.getColumnCount();
            for (int i = 1; i <= columnCount; i++) {
                System.out.println("列名:" + rsmd.getColumnName(i) + ",数据类型:" + rsmd.getColumnTypeName(i) +
                                   ",列的长度:" + rsmd.getColumnDisplaySize(i));
            }

        } catch(SQLException | ClassNotFoundException 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();
                }
            }
        }
    }
}

执行结果如下:

在上面的代码中,我们首先创建了一个 Statement 对象,然后执行了一条 SQL 查询语句,生成了一个 ResultSet 对象。接下来,我们通过 ResultSet 对象的 getMetaData() 方法获取了 ResultSetMetaData 对象,进而获取了查询结果中列的信息并进行输出。需要注意的是,在进行列信息的获取时,列的编号从 1 开始计算。该示例代码将获取查询结果集中所有列名、数据类型以及长度等信息。

获取新增行的主键值

有很多表的主键字段值都是自增的,在某些特殊的业务环境下,当我们插入了新数据后,希望能够获取到这条新数据的主键值,应该如何获取呢?在 JDBC 中,如果要获取插入数据后的主键值,可以使用 Statement 接口的 executeUpdate() 方法的重载版本,该方法接受一个额外的参数,用于指定是否需要获取自动生成的主键值。然后,通过以下两个步骤获取插入数据后的主键值:

  1. 在执行 executeUpdate() 方法时指定一个标志位,表示需要返回插入的主键值。
  2. 调用 Statement 对象的 getGeneratedKeys() 方法,返回一个包含插入的主键值的 ResultSet 对象。
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Connection;
import java.sql.Statement;
import java.util.ResourceBundle;
import java.sql.ResultSet;

public class JDBCTest13 {
    public static void main(String[] args){

        // 通过以下代码获取属性文件中的配置信息
        ResourceBundle bundle = ResourceBundle.getBundle("jdbc");
        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. 获取连接
            conn = DriverManager.getConnection(url, user, password);

            // 3. 获取数据库操作对象
            stmt = conn.createStatement();

            // 4. 执行SQL语句
            String sql = "insert into t_user(name,password,realname,gender,tel) values('zhangsan','111','张三','男','19856525352')";
            // 第一步
            int count = stmt.executeUpdate(sql, Statement.RETURN_GENERATED_KEYS);
            // 第二步
            rs = stmt.getGeneratedKeys();
            if(rs.next()){
                int id = rs.getInt(1);
                System.out.println("新增数据行的主键值:" + id);
            }

        } catch(SQLException | ClassNotFoundException 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();
                }
            }
        }
    }
}
public class JDBCTest06 {
    public static void main(String[] args) {
        // 读取属性配置文件
        ResourceBundle bundle = ResourceBundle.getBundle("com.powernode.jdbc.jdbc");
        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.获取连接
            conn = DriverManager.getConnection(url, user, password);
            // 3.获取数据库操作对象
            stmt = conn.createStatement();
            // 4.执行SQL语句
            String sql = "insert into t_product(name,price,create_time) values('小米su7', 1.0, '2024-02-23')";
            // 注意:第二个参数是标志位,用来表示是否将新插入的数据行的主键值返回
            int count = stmt.executeUpdate(sql, Statement.RETURN_GENERATED_KEYS);
            System.out.println("插入了" + count + "条记录");
            // 获取这个新增行的主键值
            // 返回的这个rs结果集中就包含了新增行的主键值
            rs = stmt.getGeneratedKeys();
            // 通过结果集取主键值
            if(rs.next()){
                long id = rs.getLong(1);
                System.out.println("新增行的主键值:" + id);
            }

        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            // 6.释放资源
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    throw new RuntimeException(e);
                }
            }
            if (stmt != null) {
                try {
                    stmt.close();
                } catch (SQLException e) {
                    throw new RuntimeException(e);
                }
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
}

执行结果如下:

以上代码中,我们将 Statement.RETURN_GENERATED_KEYS 传递给 executeUpdate() 方法,以指定需要获取插入的主键值。然后,通过调用 Statement 对象的 getGeneratedKeys() 方法获取包含插入的主键值的 ResultSet 对象,通过 ResultSet 对象获取主键值。需要注意的是,在使用 Statement 对象的 getGeneratedKeys() 方法获取自动生成的主键值时,主键值的获取方式具有一定的差异,需要根据不同的数据库种类和版本来进行调整。

工具类

public class DbUtils {

    /**
     * 工具类的构造方法一般都是私有化的,因为工具类中的一般都是静态的,
     * 工具类就是为了方便编程,所以工具类中的方法都是直接采用“类名.”
     * 的方式访问,因此不需要new对象。
     */
    private DbUtils(){}

    // 静态变量
    private static String driver;
    private static String url;
    private static String user;
    private static String password;

    // 静态代码块
    static {
        // 在这里读取属性配置文件,给静态变量赋值
        ResourceBundle bundle = ResourceBundle.getBundle("com.powernode.jdbc.jdbc");
        driver = bundle.getString("driver");
        url = bundle.getString("url");
        user = bundle.getString("user");
        password = bundle.getString("password");

        // 在类加载的时候,注册驱动,对于整个应用程序来说,注册驱动只需要做一次即可。所以选择静态代码块。
        // 静态代码块在类加载时执行,并且只执行一次。
        try {
            Class.forName(driver);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 获取数据库连接对象
     * @return 连接对象
     * @throws SQLException
     */
    public static Connection getConnection() throws SQLException {
        // 实际上这里每一次调用 getConnection() 方法时都会获取一个全新的数据库连接对象,实际上这样效率是比较低的,后期会使用连接池进行改造。
        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) {
                throw new RuntimeException(e);
            }
        }
        if (stmt != null) {
            try {
                stmt.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
    }

}
public class JDBCTest07 {
    public static void main(String[] args) {
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            conn = DbUtils.getConnection();
            stmt = conn.createStatement();
            String sql = "insert into t_product(name,price,create_time) values('小米su7', 1.0, '2024-02-23')";
            int count = stmt.executeUpdate(sql, Statement.RETURN_GENERATED_KEYS);
            System.out.println("插入了" + count + "条记录");
            rs = stmt.getGeneratedKeys();
            if(rs.next()){
                long id = rs.getLong(1);
                System.out.println("新增行的主键值:" + id);
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            DbUtils.close(conn, stmt, rs);
        }
    }
}

使用IDEA工具编写JDBC程序

创建空的工程并设置JDK

创建一个空的工程:mypro

工程结构:

设置JDK以及编译器版本:

创建一个模块

将驱动加入到CLASSPATH

在模块jdbc下创建一个目录:lib

将mysql的驱动jar包拷贝到lib目录当中:

将jar包加入到classpath:

编写JDBC程序

新建软件包:com.powernode.jdbc

新建JDBCTest01类:

在JDBCTest01类中编写main方法,main方法中编写JDBC代码:

package com.powernode.jdbc;

import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Connection;
import java.sql.Statement;
import java.util.ResourceBundle;
import java.sql.ResultSet;

public class JDBCTest01 {
    public static void main(String[] args){

        // 通过以下代码获取属性文件中的配置信息
        ResourceBundle bundle = ResourceBundle.getBundle("com.powernode.jdbc.jdbc");
        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. 获取连接
            conn = DriverManager.getConnection(url, user, password);

            // 3. 获取数据库操作对象
            stmt = conn.createStatement();

            // 4. 执行SQL语句
            String sql = "select id,name,password from t_user";
            rs = stmt.executeQuery(sql);
            while (rs.next()) {
                int id = rs.getInt("id");
                String name = rs.getString("name");
                String pwd = rs.getString("password");
                System.out.println(id + "," + name + "," + pwd);
            }

        } catch(SQLException | ClassNotFoundException 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();
                }
            }
        }
    }
}

提供配置文件,在com.powernode.jdbc包下新建jdbc.properties文件:

jdbc.properties文件中如下配置:

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbc?useUnicode=true&serverTimezone=Asia/Shanghai&useSSL=true&characterEncoding=utf-8
user=root
password=123456

执行结果如下:

  • 16
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java老狗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值