Java Database Connectivity
JDBC(Java Database Connectivity)是一种用于Java程序访问关系型数据库的API(应用程序接口)。它提供了一种标准的方法,允许Java程序使用SQL语句来访问和操作关系型数据库,使开发者能够编写数据库的程序。
1. JDBC的工作原理
- 加载数据库驱动:首先需要加载适当的数据库驱动程序。
- 连接数据库:使用Java程序中的
getConnection()
方法与数据库建立连接。 - 创建sql执行对象:通过
Statement
对象或PreparedStatement
对象来执行SQL语句。 - 执行SQL语句:使用上述对象执行SQL语句,需要对SQL语句进行预编译。
- 处理查询结果:使用
ResultSet
对象处理从数据库返回的查询结果。 - 释放资源:使用
close()
方法释放资源,包括ResultSet
对象、Statement
对象、Connection
对象。
2. JDBC常用类和接口
DriverManager 和 DataSource
DriverManager
是驱动管理类,用来管理JDBC驱动程序。DataSource
数据源也是用来管理JDBC驱动程序的。
这两个类的不同主要区分于连接管理的方式不同:
DriverManager
每次调用getConnection
方法都会初始化一个新的连接,使用完成后会关闭真实连接,导致资源浪费。DataSource
使用了连接池的技术,会在初始化时创建⼀定数量的数据库连接,这些连接可以重复使用,关闭时并不是真正关闭连接,而是将连接归还给连接池,以供后续使用,有效地提高资源利用率和和性能。
Connection 数据库连接
连接(connection)是一个物理的概念,它指的是一个通过网络建立的客户端和mysql服务器的一个网络连接。
Statement 对象
用于执行sql语句的对象。
Statement 和 PreparedStatement
Statement对象
:用于执行静态SQL语句并返回执行结果,由于只能执行静态语句,所以存在SQL注入的问题。PreparedStatement
:预编译SQL语句对象,SQL语句被预编译并存储在PreparedStatement
对象中,可以使用该对象多次执行SQL语句,同时可以解决SQL注⼊问题。
executeQuery() 和 executeUpdate()
executeQuery()
用于执行select操作的方法。executeUpdate()
通常用于执行insert、update、delete等操作。
ResultSet 结果集
用来接收查询sql的查询结果的结果集对象,相当于⼀个查询结果集的数据表。
3. JDBC连接MySQL的示例
- 使用
DriverManager
package jdbc; import java.math.BigDecimal;
import java.sql.*;
import java.text.MessageFormat;
import java.util.Scanner; // 使用驱动管理类DriverManager
public class demo1 { public static void main(String[] args){ Connection connection = null; Statement statement = null; ResultSet resultSet = null; try { //1. 注册驱动 (加载数据库厂商提供的驱动) 将驱动注册到DriverManager中 Class.forName("com.mysql.cj.jdbc.Driver"); //com.mysql.jdbc.Driver 是 MySQL 数据库连接器的一个类 //2. 建立数据库链接,设置对应的url ,userName,password connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/instance_db?characterEncoding=utf8" + "&allowPublicKeyRetrieval=true&useSSL=false","root","123456"); //3. 创建Statement对象,用来执行静态sql语句的对象 statement = connection.createStatement();//Statement对象容易导致sql注入,推荐使用PreparedStatement,预处理sql语句的对象,有效解决sql注入的问题 // 创建一条sql语句,(例如查询account表中指定用户的用户名和余额信息 :select name,balance from account;) System.out.println("请输入你要查询的用户名:"); Scanner scanner = new Scanner(System.in); String name = scanner.next(); String sql = "select name,balance from account where name = '" + name + "'"; //4. 执行sql语句,获得一个结果集对象 resultSet = statement.executeQuery(sql);//执行查询sql的方法 //遍历结果集获取数据 while(resultSet.next()) { String userName = resultSet.getString(1);//参数为第几列返回值 BigDecimal bigDecimal = resultSet.getBigDecimal(2); //MessageFormat.format 格式化输出,{编号}中的内容用后面的参数替换,编号从0开始 System.out.println(MessageFormat.format("用户名 = {0},账户余额 = {1}",userName,bigDecimal)); } } catch (ClassNotFoundException e) { throw new RuntimeException(e); } catch (SQLException e) { throw new RuntimeException(e); } finally { //释放连接资源 if(resultSet != null) { try { resultSet.close(); } catch (SQLException e) { throw new RuntimeException(e); } }if(statement != null) { try { statement.close(); } catch (SQLException e) { throw new RuntimeException(e); } }if(connection != null) { try { connection.close(); } catch (SQLException e) { throw new RuntimeException(e); } } } }
}
- 使用
DataSource
package jdbc; //使用数据源DataSource import com.mysql.cj.jdbc.MysqlDataSource; import javax.sql.DataSource;
import java.math.BigDecimal;
import java.sql.*;
import java.text.MessageFormat;
import java.util.Scanner; public class demo2 { public static void main(String[] args) { //创建一个MySQL数据库的数据源,并设置对应的URL、user、password信息 MysqlDataSource mysqlDataSource = new MysqlDataSource(); mysqlDataSource.setURL("jdbc:mysql://127.0.0.1:3306/instance_db?characterEncoding=utf8" + "&allowPublicKeyRetrieval=true&useSSL=false"); mysqlDataSource.setUser("root"); mysqlDataSource.setPassword("123456"); // 1. 使用JDBC的数据源接收MySQL数据库的数据源 DataSource dataSource = mysqlDataSource; Connection connection = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { // 2. 建立与指定MySQL数据库的连接 connection = dataSource.getConnection(); //创建要执行的sql语句 String sql = "select name,balance from account where name = ?";//这里用?占位符先替代后面要输入的内容,字符串的’‘会自动添加 // 3. 针对这一连接建立一个相应的sql执行对象Statement 语句,这里使用预处理sql对象PrepareStatement preparedStatement = connection.prepareStatement(sql); // 输入查询条件 System.out.println("请输入你要查询的用户名:"); Scanner scanner = new Scanner(System.in); String name = scanner.next(); preparedStatement.setString(1,name);//用真实值替换占位符?,第一个参数代表第几个占位符 // 4. 执行对应的sql语句,获得结果集对象 resultSet = preparedStatement.executeQuery(); //遍历结果集,获得查询结果 while(resultSet.next()) { String userName = resultSet.getString(1);//参数为第几列返回值 BigDecimal bigDecimal = resultSet.getBigDecimal(2); //MessageFormat.format 格式化输出,{编号}中的内容用后面的参数替换,编号从0开始 System.out.println(MessageFormat.format("用户名 = {0},账户余额 = {1}",userName,bigDecimal)); } } catch (SQLException e) { throw new RuntimeException(e); } finally { //释放连接资源 if(resultSet != null) { try { resultSet.close(); } catch (SQLException e) { throw new RuntimeException(e); } }if(preparedStatement != null) { try { preparedStatement.close(); } catch (SQLException e) { throw new RuntimeException(e); } }if(connection != null) { try { connection.close(); } catch (SQLException e) { throw new RuntimeException(e); } } } }
}
当然上述建立连接和释放资源这两操作可能经常使用,所以我们可以将这两操作封装成一个功能类中单独实现。