【MySQL】第十一弹——JDBC编程
文章目录
- 🌍什么是JDBC
- 🌍为什么使用JDBC
- 🌍使用JDBC
- 🪐创建Maven工程并配置国内镜像
- 🪐JDBC使用过程
- 💫1.使用DriverManager
- 💫2.使用DataSource对DriverManager进行优化
- 💫DriverManager与DataSource的区别
- 🪐示例执行一个INSERT 语句
🌍什么是JDBC
JDBC(Java Data Base Connectivity,Java数据库连接)是Java程序和数据库之间的桥梁,包含了一套Java定义的用于执行SQL语句的接口,使开发者能够编写数据库的程序 JDBC的主要作用:与数据库建立连接,发送SQL语句和处理数据库执行结果
接口是一套规则,接口中定义系统方法,这些方法由具体的实现类去完成实现逻辑
JDBC的工作原理:简简洁地概括为加载驱动、建立连接、创建Statement、执行SQL、处理结果和关闭资源
🌍为什么使用JDBC
不同数据库对数据的编解码:这些对于数据的具体操作有数据库厂商来实现,不要让Java程序员再去处理数据之间的差异
🌍使用JDBC
🪐创建Maven工程并配置国内镜像
Bundled (Maven3) 使用IDEA中内置的Maven
Maven类似于应用商店,在Maven仓库中维护了所有的Java工程需要用到的依赖,默认仓库是国外的,我们要修改成国内的
修改内置Maven的配置,需要找到IDEA的安装路径
①.Moudle一个Maven项目
②.创建一个Maven项目
🪐JDBC使用过程
💫1.使用DriverManager
- 1.加载数据库厂商的驱动包 -通过数据库厂商提供的驱动来操作数据库
import java.sql.DriverManager;
// 1. 加载数据库厂商提供的驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//通过完全限定名加载指定的类到JVM
- 2.建立连接
// 2. 获取数据库连接
connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/java?characterEncoding=utf8" + "&allowPublicKeyRetrieval=true&useSSL=false", "root", "123456");
MySQL数据库连接URL格式:jdbc:mysql://服务器地址:端口/数据库名?参数名=值[&参数名=值]…
- 3.创建Statement -用来执SQL的对象
// 3. 创建Statement对象
statement=connection.createStatement();
- 4.定义SQL
// 4. 定义SQL
System.out.println("请输入学生姓名:");
Scanner scanner = new Scanner(System.in);
// 接收用户的输入
String name = scanner.next();
String sql = "select student_id, sn, name, mail, class_id from student where name = '" + name + "'";
- 5.执行SQL语句(两种方式)
statement.executeQuery(sql); //执行select语句
statement.executeUpdate(sql);//执行 update delete insert 语句
// 5. 执行SQL,获取查询结果
resultSet = statement.executeQuery(sql);
- 6.对结果集进行遍历,获取数据
// 6. 对结果集进行遍历,获取数据
// 如果一下条有记录,返回true,没有则返回false
while (resultSet.next()) {
// 获取学生Id
long stuId = resultSet.getLong(1);
String stuSn = resultSet.getString(2);
String stuName = resultSet.getString(3);
String stuMail = resultSet.getString(4);
long classId = resultSet.getLong(5);
System.out.println(MessageFormat.format("学生编号={0}, 学号={1}, 学生姓名={2}, 邮箱={3}, 班级编号={4}", stuId, stuSn,
stuName, stuMail, classId));}
- 7.处理结果释放资源和关闭连接
以上代码都已在try-catch 中捕获异常
不管成功与否都要释放资源关闭连接 所以以下代码写在finally代码块中
finally {// 依次释放资源,关闭连接if (resultSet != null) {try {resultSet.close();} catch (SQLException e) {e.printStackTrace();}}if (statement != null) {try {statement.close();} catch (SQLException e) {e.printStackTrace();}}if (connection != null) {try {connection.close();} catch (SQLException e) {e.printStackTrace();}}
完整代码:
/*** Created with IntelliJ IDEA.* Description:* User: xhx_1* Date: 2025-05-25* Time: 12:53*/
import java.sql.*;
import java.text.MessageFormat;
import java.util.Scanner;
public class Demo01_DriverManager {public static void main(String[] args) {Connection connection = null;Statement statement = null;ResultSet resultSet = null;try {// 1. 加载数据库厂商提供的驱动Class.forName("com.mysql.cj.jdbc.Driver");// 2. 获取数据库连接connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/java?characterEncoding=utf8" +"&allowPublicKeyRetrieval=true&useSSL=false", "root", "123456");// 3. 创建Statement对象statement = connection.createStatement();// 4. 定义SQL并执行SQL语句System.out.println("请输入学生姓名:");Scanner scanner = new Scanner(System.in);// 接收用户的输入String name = scanner.next();String sql = "select student_id, sn, name, mail, class_id from student where name = '" + name + "'";// 5. 执行SQL,获取查询结果resultSet = statement.executeQuery(sql);// 6. 对结果集进行遍历,获取数据// 如果一下条有记录,返回true,没有则返回falsewhile (resultSet.next()) {// 获取学生Idlong stuId = resultSet.getLong(1);String stuSn = resultSet.getString(2);String stuName = resultSet.getString(3);String stuMail = resultSet.getString(4);long classId = resultSet.getLong(5);System.out.println(MessageFormat.format("学生编号={0}, 学号={1}, 学生姓名={2}, 邮箱={3}, 班级编号={4}", stuId, stuSn,stuName, stuMail, classId));}} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();} finally {// 依次释放资源,关闭连接if (resultSet != null) {try {resultSet.close();} catch (SQLException e) {e.printStackTrace();}}if (statement != null) {try {statement.close();} catch (SQLException e) {e.printStackTrace();}}if (connection != null) {try {connection.close();} catch (SQLException e) {e.printStackTrace();}}}}}
使用这种方式进行JDBC的使用没有安全性问题-SQL注入
为解决SQL注入的安全性问题,我们需要对DriverManager进行两点优化
①.Statement 是执行静态SQL
我们换成PrepardStatement 这个预处理的SQL对象
②.DriverManger.getConnectin() 每次获取的是一个物理连接
执行过后直接关闭连接 但是我们还想接着用
就需要DataSourse对象,一个链接可以执行很多SQL,直到关闭数据源
通过一个连接池去管理很多个连接,当需要SQL执行的时候,从连接池里拿一个空闲的空间出来,用完返还给连接池 -有很多工具都用的是连接池来管理连接,像是Mybatis
💫2.使用DataSource对DriverManager进行优化
- 1.通过数据源获取数据库连接
// 1. 通过数据源获取数据库连接
connection = dataSource.getConnection();
- 2.获取预处理SQL执行对象
// 2. 获取预处理SQL执行对象
// 定义要执行的SQL
String sql = "select student_id, sn, name, mail, class_id from student where name = ?";
statement = connection.prepareStatement(sql);// 接收用户的输入
System.out.println("请输入学生姓名:");
Scanner scanner = new Scanner(System.in);
String name = scanner.next();
- 3.用真实值替换占位符
// 3. 用真实值替换占位符
statement.setString(1, name);
- 4.执行SQL,获取结果集
// 4. 执行SQL,获取结果集
resultSet = statement.executeQuery();
- 5.遍历结果集
// 5. 遍历结果集
while (resultSet.next()) {
// 获取学生Id
long stuId = resultSet.getLong("student_id");
String stuSn = resultSet.getString(2);
String stuName = resultSet.getString(3);
String stuMail = resultSet.getString(4);
long classId = resultSet.getLong(5);System.out.println(MessageFormat.format("学生编号={0}, 学号={1}, 学生姓名={2}, 邮箱={3}, 班级编号={4}", stuId, stuSn,stuName, stuMail, classId));
}
- 6.释放资源,关闭连接
finally {// 依次释放资源,关闭连接if (resultSet != null) {try {resultSet.close();} catch (SQLException e) {e.printStackTrace();}}if (statement != null) {try {statement.close();} catch (SQLException e) {e.printStackTrace();}}if (connection != null) {try {connection.close();} catch (SQLException e) {e.printStackTrace();}}}
💫DriverManager与DataSource的区别
- DriverManager与DataSource都可以获取到数据库的连接,但他们之间存在着一些区别,主要在与连接的管理方式和资源利用效率
- 连接方式不同:
– 1.DriverManager每次调用getConnection方法都会初始化一个新的连接,使用完成后会关闭真实连接,导致资源浪费
– 2.DataSource使用了连接池的技术,会在初始化时创建一定数量的数据库连接,这些连接可以可以重复使用,关闭时并不是真正的关闭连接,而是将连接归还给连接池,以供后续使用,有效的提高资源利用率和性能
🪐示例执行一个INSERT 语句
- 1.获取数据库连接
// 1. 获取数据库连接
connection = DBUtil.getConnection();
- 2.定义SQL
// 2. 定义SQL
String sql = "insert into student (sn, name, mail, class_id) values (?,?,?,?)";
- 3.定义SQL的预处理对象
// 3. 定义SQL预处理对象
statement = connection.prepareStatement(sql);
- 4.接收用户参数
// 4. 接收用户参数System.out.println("请输入学号:");
Scanner scanner = new Scanner(System.in);
String sn = scanner.next();System.out.println("请输入姓名:");
String name = scanner.next();System.out.println("请输入邮箱:");
String mail = scanner.next();System.out.println("请输入班级编号:");
Long classId = Long.valueOf(scanner.next());
不使用nextLong()是因为他会清理缓存,后序insert数据会出现问题
- 5.用真实数据填充占位符
// 5. 用真实数据填充占位符
statement.setString(1, sn);
statement.setString(2, name);
statement.setString(3, mail);
statement.setLong(4, classId);
- 6.执行SQL获取结果
// 6. 执行SQL获取结果
int row = statement.executeUpdate();
- 7.判断结果
// 7. 判断结果if (row == 1) {System.out.println("插入成功");
} else {System.out.println("插入失败");
}
- 8.释放资源,关闭连接
finally {
// 释放资源,关闭连接
DBUtil.close(null, statement, connection);
}
使用DBUtil封装
mport com.mysql.cj.jdbc.MysqlDataSource;import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;public class DBUtil {// 数据源private static DataSource dataSource = null;// 数据库连接串private static final String URL = "jdbc:mysql://127.0.0.1:3306/java113?characterEncoding=utf8" +"&allowPublicKeyRetrieval=true&useSSL=false";// 用户名private static final String USER = "root";// 密码private static final String PASSWORD = "123456";// 当类加载到JVM的时候,执行数据源的初始化static {MysqlDataSource mysqlDataSource = new MysqlDataSource();mysqlDataSource.setURL(URL);mysqlDataSource.setUser(USER);mysqlDataSource.setPassword(PASSWORD);dataSource = mysqlDataSource;}/*** 构造方法私有化,防止new这个对象*/private DBUtil() {}/*** 获取数据库连接* @return* @throws SQLException*/public static Connection getConnection () throws SQLException {return dataSource.getConnection();}/*** 释放资源,关闭连接* @param resultSet* @param statement* @param connection*/public static void close(ResultSet resultSet, Statement statement, Connection connection) {if (resultSet != null) {try {resultSet.close();} catch (SQLException e) {e.printStackTrace();}}if (statement != null) {try {statement.close();} catch (SQLException e) {e.printStackTrace();}}if (connection != null) {try {connection.close();} catch (SQLException e) {e.printStackTrace();}}}
Demo04_Insert
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Scanner;public class Demo04_Insert {public static void main(String[] args) {Connection connection = null;PreparedStatement statement = null;// 插入操作需不需要定义结果集对象? -- 不用,因为insert返回的是受影响的行数try {// 1. 获取数据库连接connection = DBUtil.getConnection();// 2. 定义SQLString sql = "insert into student (sn, name, mail, class_id) values (?,?,?,?)";// 3. 定义SQL预处理对象statement = connection.prepareStatement(sql);// 4. 接收用户参数System.out.println("请输入学号:");Scanner scanner = new Scanner(System.in);String sn = scanner.next();System.out.println("请输入姓名:");String name = scanner.next();System.out.println("请输入邮箱:");String mail = scanner.next();System.out.println("请输入班级编号:");Long classId = Long.valueOf(scanner.next());// 5. 用真实数据填充占位符statement.setString(1, sn);statement.setString(2, name);statement.setString(3, mail);statement.setLong(4, classId);// 6. 执行SQL获取结果int row = statement.executeUpdate();// 7. 判断结果if (row == 1) {System.out.println("插入成功");} else {System.out.println("插入失败");}} catch (SQLException e) {e.printStackTrace();} finally {// 释放资源,关闭连接DBUtil.close(null, statement, connection);}}
}
好的,到此MySQL数据库的基础知识我们已经讲解结束,后序关于数据库的重要操作比如Mybatis的应用,会在JavaEE的专栏讲解,大家可以关注后续博客更新