JDBC

122 阅读5分钟

JDBC

JDBC,全称Java Database Connectivity,它是一个用于Java编程语言的应用程序接口(API),定义了客户端如何访问数据库,是一个基于Java的数据访问技术,用于Java数据库连接。

JDBC的功能

它允许用户通过不同的实现来加载和注册正确的Java包,并使用JDBC驱动程序管理器作为创建JDBC连接的工厂。JDBC连接支持创建和执行语句。这些语句可以是更新语句,如SQL的CREATE, INSERT, UPDATE和DELETE,也可以是查询语句,如SELECT。此外,还可以通过JDBC连接调用存储过程。

JDBC使用以下类之一来表示语句:

  • Statement – 每次都将语句发送到数据库服务器。
  • PreparedStatement – 语句被缓存,然后在数据库服务器上预先确定执行路径,允许以高效的方式多次执行。
  • CallableStatement – 用于执行存储过程。

JDBC编程步骤包括:

  • 加载驱动程序:Class.forName(driverClass)
  • 获得数据库连接:DriverManager.getConnection(url, user, password)
  • 创建Statement/PreparedStatement对象:conn.createStatement() 或 conn.prepareStatement(sql)
  • 执行SQL语句:stmt.executeQuery(sql) 或 stmt.executeUpdate(sql) 或 pstmt.execute()
  • 处理结果集:ResultSet rs = stmt.executeQuery(sql) 或 int n = stmt.executeUpdate(sql)
  • 关闭资源:rs.close(), stmt.close(), pstmt.close(), conn.close() //按照打开的顺序逆序关闭

预先准备

在使用JDBC之前我们需要下载MySQL并进行导包

Java MySQL Connector/J 包下载详见:MySQL Connector/J

1.将下载的jar包拖进lib文件夹中,右键->Add as library->OK

2.在MySQL中创建一个table

mysql_table.png

示例

import java.sql.*;
public class JDBCTest {
    public static final String URL = "jdbc:mysql://127.0.0.1:3306/school";
    public static final String USER = "root";
    public static final String PASSWORD = "111111";
    public static final String DRIVER = "com.mysql.jdbc.Driver";
​
    public static Connection connection;
    public static Statement statement;
    public static ResultSet resultSet;
​
    public static void main(String[] args) throws SQLException {
        try{
            //1.加载驱动程序
            Class.forName(DRIVER);
            System.out.println("数据库驱动加载成功!");
            //2.获取数据库连接
            connection = DriverManager.getConnection(URL,USER,PASSWORD);
            //3.获取数据库操作对象
            statement = connection.createStatement();
            System.out.println("数据库连接成功!");
            //4.SQL语句
            ResultSet resultSet = statement.executeQuery("select * from student");
​
            while(resultSet.next()) {
                int id = resultSet.getInt(1);
                String name = resultSet.getString(2);
                String gender = resultSet.getString(3);
                int age = resultSet.getInt(4);
                System.out.println("id:" + id + ", name:" + name + ", gender:" + gender + ", age:" + age);
            }
            //5.完成所有操作,关闭所有连接,谁先用谁先关闭
        } catch(Exception e) {
            e.printStackTrace();
        } finally {
            statement.close();
            connection.close();
        }
    }
}

输出结果:

数据库驱动加载成功!
数据库连接成功!
id:1, name:Tom, gender:male, age:12
id:2, name:Lowell, gender:male, age:20
id:3, name:Frank, gender:male, age:36

封装JDBCUtils类

因为每次查询都要重新写配置文件,因此我们将配置文件封装起来,在src下创建db.properties配置文件,写入配置项

db_properties.png

同时也将JDBC代码封装

import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
​
public class JDBCUtils {
    private static String driver;
    private static String url;
    private static String user;
    private static String password;
​
    //通过静态代码块,来预先处执行读取配置文件的配置项,做预处理
    static {
        try{
            JDBCUtils.class.getClassLoader();
            //读取配置文件
            InputStream inputStream = ClassLoader.getSystemResourceAsStream("db.properties");
​
            //加载对象
            Properties properties = new Properties();
            properties.load(inputStream);
​
            //读取配置项
            driver = properties.getProperty("driver");
            url = properties.getProperty("url");
            user = properties.getProperty("user");
            password = properties.getProperty("password");
​
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
​
    //测试是否加载成功
    public static void Test() {
        System.out.println("load success");
    }
​
    //创建单例,获取配置项
    public static Connection getConnetion() throws SQLException {
        return DriverManager.getConnection(url,user,password);
    }
​
    //释放,关闭结果,关闭仓库,关闭数据库连接
    public static void close(Connection connection, Statement statement) throws SQLException {
        if(statement != null) {
            statement.close();
        }
        if(connection != null) {
            connection.close();
        }
    }
​
    public static void close(Connection connection, Statement statement, ResultSet resultSet) throws SQLException {
        if(statement != null) {
            statement.close();
        }
        if(connection != null) {
            connection.close();
        }
        if(resultSet != null) {
            resultSet.close();
        }
    }
}
​

创建测试类,测试是否能够成功加载

import com.goole.util.JDBCUtils;
public class JDBCUtilsDemo {
    public static void main(String[] args) {
        JDBCUtils.Test();
    }

输出结果:

load success

executeUpdate()实现增删改

示例

package com.jdbc;
​
import com.goole.util.JDBCUtils;
import org.junit.Test;
import java.sql.*;
​
public class JDBCUtilsDemo {
    public Connection connection;
    public Statement statement;
​
    @Test
    public void insertTest() throws SQLException {
        try{
            connection = JDBCUtils.getConnetion();
            statement = connection.createStatement();
            //System.out.println("connection = " + connection);
​
            String sql = "insert into student(id,name) values(15,'Tin')";
            int res = statement.executeUpdate(sql);
​
            if(res > 0) {
                System.out.println("Insert successfully!");
            }
        }catch(Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.close(connection,statement);
        }
​
    }
​
    @Test
    public void updateTest() throws SQLException {
        try{
            connection = JDBCUtils.getConnetion();
            statement = connection.createStatement();
            System.out.println("connection = " + connection);
​
            String sql = "update student set name = 'Jerry' where id = '11'";
            int res = statement.executeUpdate(sql);
​
            if(res > 0) {
                System.out.println("Update successfully!");
            }
        }catch(Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.close(connection,statement);
        }
    }
​
    @Test
    public void deleteTest() throws SQLException {
        try{
            connection = JDBCUtils.getConnetion();
            statement = connection.createStatement();
            System.out.println("connection = " + connection);
​
            String sql = "delete from student where id = '10'";
            int res = statement.executeUpdate(sql);
​
            if(res > 0) {
                System.out.println("Delete successfully!");
            }
        }catch(Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.close(connection,statement);
        }
    }
​
    @Test
    public void selectTest() throws SQLException {
        try{
            connection = JDBCUtils.getConnetion();
            statement = connection.createStatement();
            System.out.println("connection = " + connection);
​
            String sql = "select * from student";
            ResultSet res = statement.executeQuery(sql);
​
            while(res.next()) {
                int id = res.getInt(1);
                String name = res.getString(2);
                String gender = res.getString(3);
                int age = res.getInt(4);
                System.out.println("id:" + id +", name:" + name + ", gender:" + gender + ", age:" + age);
            }
        }catch(Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.close(connection,statement);
        }
    }
}
​
​

增删改结果:

student_table.png

查询结果:

connection = com.mysql.jdbc.JDBC4Connection@6e509ffa
id:1, name:Tom, gender:male, age:12
id:2, name:Lowell, gender:male, age:20
id:3, name:Frank, gender:male, age:36
id:8, name:Jim, gender:female, age:25
id:11, name:Jerry, gender:null, age:0
id:15, name:Tin, gender:null, age:0
id:37, name:, gender:null, age:0

PreparedStatement和问号占位符

什么是PreparedStatement?

preparedstatement是一个接口,它表示一个预编译的SQL语句。它可以提高SQL语句的执行效率,增加代码的可读性,防止SQL注入攻击,以及方便地设置参数值。

SQL注入攻击是一种利用Web应用程序中存在的安全漏洞,通过在输入框中插入恶意的SQL代码,从而实现对数据库的非法操作。

要使用preparedstatement,你需要先通过Connection对象的prepareStatement方法创建一个preparedstatement对象,并传入一个包含占位符(?) 的SQL语句。然后,你可以通过setXXX方法为每个占位符设置对应的值,其中XXX表示参数的数据类型,如setInt, setString等。最后,你可以通过executeQuery或executeUpdate方法执行SQL语句,并返回ResultSet或int值。

例如,如果你想查询员工表中ID为1001的员工的信息,你可以这样写:

PreparedStatement ps = con.prepareStatement("select * from Employee where ID = ?");
ps.setInt(1, 1001);
ResultSet rs = ps.executeQuery();

这样,你就不需要拼接字符串来构造SQL语句,也不需要担心ID的值是否包含特殊字符或关键字。

将之前所有的Statement类型改为PreparedStatement类型

package com.jdbc;
​
import com.goole.util.JDBCUtils_PreparedStatement;
​
import java.sql.ResultSet;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Scanner;
​
public class JDBCUtilsDemo_1 {
​
        public static Connection connection;
        public static PreparedStatement preparedStatement;
        Scanner scanner = new Scanner(System.in);
​
        public static void main(String[] args) {
            try {
                //1.获取数据库连接和操作对象
                connection = JDBCUtils_PreparedStatement.getConnetion();
​
                //2.用户输入信息,使用占位符的sql语句,更新一条数据
                String sql = "INSERT INTO student(id, name) values(?, ?)";
                System.out.println("请先输入id,再输出姓名,用回车隔开:");
                Scanner scanner = new Scanner(System.in);
                int id = scanner.nextInt();
                String name = scanner.next();
​
                //3.preparedStatement传入带占位符的sql语句,set方法设置每一个位置的值,并执行更新操作
                preparedStatement = connection.prepareStatement(sql);
                preparedStatement.setInt(1, id);     //第一个set对应第一个?
                preparedStatement.setString(2, name);//第二个set对应第二个?
                int res = preparedStatement.executeUpdate();
​
                //4.判断数据是否更新成功
                if (res != 0) {
                    System.out.println("Update success");
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    //5.调用重载方法,释放资源
                    JDBCUtils_PreparedStatement.close(connection, preparedStatement);
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
​
}
​
请先输入id,再输出姓名,用回车隔开:
5
Harry
Update success

结果:

run_res.png

其他增删改查大同小异,只需要修改SQL语句