当前位置: 首页 > news >正文

Java数据库连接——JDBC

目录

1、JDBC简介

2、JDBC应用

2.1 建立数据库连接

2.1.1 DriverManager静态方法获取连接

2.1.2 DataSource对象获取

2.2 获取SQL执行对象

2.2.1 SQL注入

2.2.2 Statement(执行静态SQL)

2.2.3 PreparedStatement(预处理的SQL执行对象)

2.3 执行SQL并返回结果

2.4 关闭连接,释放资源

3、示例


1、JDBC简介

JDBC(Java Data Base Connectivity,Java数据库连接)是Java程序和数据库之间的桥梁,包含 了⼀套Java定义的用于执行SQL语句的接口,使开发者能够编写数据库的程序。JDBC 的主要作用是: 与数据库建立连接、发送SQL语句和处理数据库执行结果。

正常来说,访问数据库需要经过以下几个重要步骤:

  1. 确定数据库服务器的地址,端口号(数据源)
  2. 建立连接,用户名、密码(不同的数据库以哪种协议建立连接)
  3. 发生要执行的SQL(以什么样的形式发送——需要考虑编码的格式(协议))
  4. 接收返回的结果(结果集(select)、受影响的行数(insert、...))(需要考虑一哪种协议解析结果)
  5. 关闭连接(释放资源,关闭连接)

JDBC是Java平台提供的接口,其中具体的实现是由不同的数据库厂商来完成的,数据库厂商实现完后将其封装在不同的方法中,Java开发者可以使用这些封装好的方法,操作数据库。

JDBC工作原理简洁地概括为:

  1. 加载驱动
  2. 建立连接
  3. 创建Statement(获取SQL执行对象)
  4. 执行SQL并返回结果
  5. 处理结果,关闭资源

2、JDBC应用

2.1 建立数据库连接

2.1.1 DriverManager静态方法获取连接

获取数据库连接的第一种方式:以驱动管理类DriverManager获取连接。

注意:该方式获取的是物理连接,即每次运行时都会重新打开一个客户端工具(随用随开)。

举个例子:比如公司中有了一个新业务,老板为完成这个业务招了十个员工,业务完成后立刻把他们炒了。过了一段时间,公司又有了一个新业务,老板又重新招人,完成业务又把他们开了。(随用随招)

因此,该方法效率低下,不推荐。

 //1. 加载数据库厂商提供的驱动//通过完全限定名记载指定的类到JVMClass.forName("com.mysql.cj.jdbc.Driver");//2. 获取数据库连接(物理连接)connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test2?characterEncoding=utf8&" +"allowPublicKeyRetrieval=true&useSSL=false", "root", "111111");

2.1.2 DataSource对象获取

通过数据源DataSource对象获取,一个连接可以执行很多SQL,直到关闭数据源。

这种方式是通过一个连接池去管理很多个连接,当需要SQL执行时,就从连接池里拿出一个连接,用完后返还给连接池。

推荐在实际开发中使用这种方式。

        //1. 定义MySQL数据源对象(连接池)MysqlDataSource mysqlDataSource = new MysqlDataSource();//2. 设置数据库连接串mysqlDataSource.setURL("jdbc:mysql://127.0.0.1:3306/test2?characterEncoding=utf8" +"&allowPublicKeyRetrieval=true&useSSL=false");//用户mysqlDataSource.setUser("root");//密码mysqlDataSource.setPassword("111111");//定义JDBC的数据源对象DataSource dataSource = mysqlDataSource;//1. 通过数据源获得数据库连接对象connection = dataSource.getConnection();

2.2 获取SQL执行对象

2.2.1 SQL注入

SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应 用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。

2.2.2 Statement(执行静态SQL)

Statement是用于执行静态SQL语句并返回执行结果的对象

注意:该方式存在SQL注入的安全问题!!!

如下图:该方式是通过字符串拼接的方式组装完成的SQL语句,字符串拼接形式构造SQL语句时,如果不处理参数中的特殊字符就会造成SQL注入,这是⼀个非常严重的安全性问题。

//定义Statement 
Statement statement = null;
//3. 创建Statement对象
statement = connection.createStatement();
//4. 定义SQL并执行SQL语句
Scanner scanner = new Scanner(System.in);
System.out.println("请输入要查询的学生的姓名:");
//接收用户输入
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);

2.2.3 PreparedStatement(预处理的SQL执行对象)

预编译SQL语句对象,SQL语句被预编译并存储在PreparedStatement对象中,可以使用该对象多次执行SQL语句,同时可以解决SQL注入问题。

动态参数用占位符 ? 表示。

简单以上文SQL注入的输入为例,该方式直接将用户输入的内容全部当做name的值(利用占位符),直接在数据表中通过输入值来查找相应记录。

注意:使用真实值替换占位符时,使用setString/setLong/....方法,编号从1开始,有多少个参数就设置多少个值。

            //定义要执行的SQLString sql = "select student_id, sn, name, mail, class_id from student where name = ?";Scanner scanner = new Scanner(System.in);//2. 获取预处理SQL执行对象statement = connection.prepareStatement(sql);//接收用户输入System.out.println("请输入要查询的学生的姓名:");String name = scanner.next();//3. 用真实值替换占位符statement.setString(1, name);

2.3 执行SQL并返回结果

执行select语句,返回结果集(ResultSet结果集接收):

//定义结果集对象
ResultSet resultSet = null; 
//4. 执行SQL,获取结果集对象
resultSet = statement.executeQuery();
//迭代打印结果集
//最初游标位于第⼀⾏之前,调⽤next⽅法将游标移动到下⼀⾏,
//当ResultSet中没有更多的数据⾏时返回false
while (resultSet.next()) {long stuId = resultSet.getLong(1);String stuSn = resultSet.getString(2);String stuName = resultSet.getString(3);String stuMail = resultSet.getString(4);long stuClassId = resultSet.getLong(5);System.out.println(MessageFormat.format("学生编号={0}, 学号={1}, 姓名={2}, 邮箱={3}, 班级编号={4}",stuId, stuSn, stuName, stuMail, stuClassId));
}

执行update、delete、insert操作,返回所影响的行数:

int row = statement.executeUpdate();

2.4 关闭连接,释放资源

自下而上,依次关闭。

// 依次释放资源,关闭连接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);}}

3、示例

封装数据库连接、资源关闭方法:

package org.example.utils;import 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;/*** Created with IntelliJ IDEA.* Description:封装方法* User: dings* Date: 2024-09-21* Time: 14:53*/
public class DBUtils {private static DataSource dataSource = null;private static MysqlDataSource mysqlDataSource = new MysqlDataSource();private static String URL = "jdbc:mysql://127.0.0.1:3306/test2?characterEncoding=utf8&allowPublicKeyRetrieval=true&useSSL=false";private static String USER = "root";private static String PASSWORD = "111111";private DBUtils() {}//构造方法私有化static {mysqlDataSource.setURL(URL);mysqlDataSource.setUser(USER);mysqlDataSource.setPassword(PASSWORD);dataSource = mysqlDataSource;}public static Connection getConnection() throws SQLException {return dataSource.getConnection();}public static void close(ResultSet resultSet, Statement statement, Connection connection) {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);}}}
}

实现记录的插入:

package org.example;import org.example.utils.DBUtils;import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Scanner;/*** Created with IntelliJ IDEA.* Description:向表中插入记录* User: dings* Date: 2024-09-21* Time: 15:06*/
public class Demo03_insert {public static void main(String[] args) {Connection connection = null;PreparedStatement statement = null;try {connection = DBUtils.getConnection();String sql = "insert into student (sn, name, mail, class_id) values (?,?,?,?)";statement = connection.prepareStatement(sql);Scanner scanner = new Scanner(System.in);System.out.println("请输入学号:");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());//编号从1开始statement.setString(1, sn);statement.setString(2, name);statement.setString(3, mail);statement.setLong(4, classId);int row = statement.executeUpdate();if(row == 1) {System.out.println("插入成功!");}else {System.out.println("插入失败!");}} catch (SQLException e) {e.printStackTrace();}finally {// 释放资源,关闭连接DBUtils.close(null, statement, connection);}}
}

END


http://www.mrgr.cn/news/33888.html

相关文章:

  • 使用 PyTorch 实现 AlexNet 进行 MNIST 图像分类
  • 面试必修技能之鸿蒙并发编程及其优化策略
  • Day44 | 动态规划 :状态机DP 买卖股票的最佳时机IV买卖股票的最佳时机III
  • LeetCode【0026】删除有序数组中的重复项
  • JAVA学习日记(十五) 数据结构
  • leetcode 148. 排序链表 中等
  • 智能农业系统——土壤养分运移转化
  • 一些迷你型信息系统 - 2
  • 如何在 MySQL Workbench 中修改表数据并保存??
  • 华为杯”第十二届中国研究生数学建模竞赛-B题: 数据的多流形结构分析
  • Hive之任务优化
  • 【Android】 IconFont的使用
  • 【ShuQiHere】 掌握卡诺图 (Karnaugh Map)——简化布尔表达式的利器
  • 01_两数之和
  • 情指行一体化平台建设方案和必要性-———未来之窗行业应用跨平台架构
  • 数字范围按位与
  • Hadoop入门两道面试题
  • AI教你学Python 第17天 :小项目联系人管理系统
  • 【漏洞复现】用友 NC-Cloud queryStaffByName Sql注入漏洞
  • 计算机毕业设计PySpark+Scrapy农产品推荐系统 农产品爬虫 农产品商城 农产品大数据 农产品数据分析可视化 PySpark Hadoop
  • 【MySQL】获取最近7天和最近14天的订单数量,使用MySQL详细写出,使用不同的方法
  • 伊丽莎白·赫莉为杂志拍摄一组素颜写真,庆祝自己荣膺全球最性感女人第一名
  • 原子结构与电荷
  • 【Linux 21】线程安全
  • 【最快最简单的排序 —— 桶排序算法】
  • wgan 生成器 光是用噪声生成数据 还是噪声加输入数据