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

[MySQL] JDBC

1.JDBC 的简介

JDBC (Java Data Base Connectivity,Java数据库连接)是 Java 程序和数据库之间的桥梁 , 包含了一套 Java 定义于执行 SQL 语句的接口 , 使开发者能够编写数据库的程序

JDBC 的主要作用 : 与数据库建立连接 , 发送 SQL 语句 , 处理数据库执行结果

JDBC 工作原理 : 加载驱动 , 建立连接 , 创建 Statement , 执行 SQL , 处理结果 , 关闭资源

2.为什么使用 JDBC

创建客户端操作数据库的过程 :

  1. 确定连接地址 , 添加端口号(数据源)
  2. 连接到数据库服务(数据库连接)
  3. 发送 SQL 语句(执行对象)
  4. 得到返回结果集并显示(结果集)
  5. 关闭连接(释放资源)

Java 采取的做法是把上述操作步骤定义了相应的接口 , 具体实现交给数据库厂商去做 , Java 程序员只需按照需要调用接口中的定义方法即可 , 这样不论使用什么数据库 , 都对 Java 程序没有任何影响 , 即使换一个数据库 , 也只需要换一下相应厂商的是是实现依赖

JDBC 使用过程可以概括为 : 加载数据库厂商的驱动包 , 建立连接 , 创建 Statement , 执行 SQL , 处理结果释放资源 , 关闭连接

3.使用 JDBC

3.1 创建 Maven 工程并配置国内镜像

  • 修改 Maven 配置文件 , 在<mirrors></mirrors>标签中替换为以下代码
<mirrors><!-- mirror| Specifies a repository mirror site to use instead of a given repository. The repository that| this mirror serves has an ID that matches the mirrorOf element of this mirror. IDs are used| for inheritance and direct lookup purposes, and must be unique across the set of mirrors.|--><!-- 加入如下mirror节点 使用国内阿里云仓库镜像  开始 --><mirror><id>aliyunmaven</id><mirrorOf>*</mirrorOf><name>阿里云公共仓库</name><url>https://maven.aliyun.com/repository/public</url></mirror><mirror><id>central</id><mirrorOf>*</mirrorOf><name>aliyun central</name><url>https://maven.aliyun.com/repository/central</url></mirror><mirror><id>spring</id><mirrorOf>*</mirrorOf><name>aliyun spring</name><url>https://maven.aliyun.com/repository/spring</url></mirror><!-- 加入如下mirror节点 使用国内阿里云仓库镜像  结束--></mirrors>
  • IDEA 中 Maven 的配置文件夹 : IDEA 安装目录/plugins/maven/lib/maven3/conf/settings.xml

3.2 获取 MySQL 的驱动包

在 mvnrepository.com 下搜索 MySQL , 找到最新的驱动包

3.3 修改 pom.xml 文件

在 maven 工程中的 pom.xml 中的<dependencies></denpendencies>标签中添加 MySQL 依赖

如图所示:

4.创建工程

import java.sql.*;
import java.text.MessageFormat;
import java.util.Scanner;public class test1 {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/bit_1027?characterEncoding=utf8" +"&allowPublicKeyRetrieval=true&useSSL=false","root","119856");// 3. 创建 statement对象statement = connection.createStatement();// 4. 定义SQL并执行SQL语句System.out.println("请输入学生姓名");Scanner scanner = new Scanner(System.in);//接收用户输入String name = scanner.next();String sql = "select id,name,gender ,age,class_id from students where name = '"+name+"'";// 5. 执行SQL, 获取查询结果集resultSet = statement.executeQuery(sql);// 6. 对结果集进行遍历 , 获取数据while(resultSet.next()){int id = resultSet.getInt(1);String stuname = resultSet.getString(2);String stugender = resultSet.getString(3);int age = resultSet.getInt(4);int class_id = resultSet.getInt(5);System.out.println(MessageFormat.format("学生编号 = {0} , 学生姓名 = {1} , 性别 = {2} , 年龄 = {3}  , 班级编号 = {4}",id,stuname,stugender,age,class_id));}} 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();}}}}
}


目标数据库 :


① 建立数据库连接


② 创建 Statement


④ 执行 SQL 语句

  • 执行 select 查询时返回的是一个结果集 , 用 ResultSet 接收
  • 执行 nsert , update , delete 操作时 , 返回的是受影响的行数 , 用 int 类型接收
  • executeQuery() , 执行返回的是一个结果集 , 通常用于 select 操作
  • executeUpdate() , 执行结果是一个整型 , 通常用于 insert , update , delete 操作


⑤ 处理结果集

  • 如果返回的是一个结果集 , 则需要遍历这个集合获取对应列的值


⑥ 释放资源

  • 在整个数据库访问的过程中的对象都需要释放 , 包括 : ResultSet,Statement和Connection, 后创建的先释放

5. 优化 1

1.SQL 注入

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

示例 : 将 正常的条件值替换为

'or/**/1=1;# 

  • 此操作仅用于理解 SQL 注入的危害,实际开发中必须使用PreparedStatement参数化查询(如之前建议的代码修改),从根源上杜绝注入风险。
  • 未经授权对系统进行注入测试属于违法行为,务必遵守法律法规和道德规范。

解决方案

使用 PreparedStatement 预编译 SQL 语句对象 , 实现参数化查询 , 杜绝 SQL 注入分享 , 符合企业级开发规范

通过 Connection 对象获取到 PreparedStatement 对象 , 需要传入 SQL 模板 , 动态参数用占位符 ? 表示

2.如果要执行别的 SQL 语句需要重复打开客户端

使用 DriverManager 每次调用 getConnection 方法都会初始化一个新的连接 , 使用完后会关闭真实连接 , 导致资源浪费

解决方案

使用 DataSource 连接池技术 , 会在初始化时 创建一定数量的数据库连接 , 这些连接可以重复使用 , 关闭时并不是真正关闭 , 而是将连接归还给连接池 , 以供后续使用 , 有效提高资源利用率和性能

import com.mysql.cj.jdbc.MysqlDataSource;import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.MessageFormat;
import java.util.Scanner;public class test2 {public static void main(String[] args) {//定义MySQL数据源对象MysqlDataSource mysqlDataSource = new MysqlDataSource();//设置数据库连接串mysqlDataSource.setURL("jdbc:mysql://127.0.0.1:3306/bit_1027?characterEncoding=utf8" +"&allowPublicKeyRetrieval=true&useSSL=false");//用户名mysqlDataSource.setUser("root");//密码mysqlDataSource.setPassword("119856");//定义JDBC的数据源对象DataSource dataSource = mysqlDataSource;//定义连接对象Connection connection = null;//定义预处理SQL执行对象PreparedStatement statement = null;//定义结果集对象ResultSet resultSet = null;try {// 1.通过数据源获取数据库连接connection = dataSource.getConnection();// 2.获取预处理SQL执行对象//定义要执行的SQLString sql = "select id,name,gender ,age,class_id from students where name = ?";statement = connection.prepareStatement(sql);//接收用户输入System.out.println("请输入学生姓名");Scanner scanner = new Scanner(System.in);String name = scanner.next();// 3.用真实姓名替代占位符statement.setString(1,name);// 4.执行SQL ,获取结果集resultSet = statement.executeQuery();//遍历结果集while(resultSet.next()){int id = resultSet.getInt(1);String stuname = resultSet.getString(2);String stugender = resultSet.getString(3);int age = resultSet.getInt(4);int class_id = resultSet.getInt(5);System.out.println(MessageFormat.format("学生编号 = {0} , 学生姓名 = {1} , 性别 = {2} , 年龄 = {3}  , 班级编号 = {4}",id,stuname,stugender,age,class_id));}//            while(resultSet.next()){//                int id = resultSet.getInt("id");//                String stuname = resultSet.getString("name");//                String stugender = resultSet.getString("gender");//                int age = resultSet.getInt("age");//                int class_id = resultSet.getInt("class_id");//                // 打印逻辑不变//            }} 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();}}}}}

6. 优化 2

1. 封装

将 获取数据库连接 和 释放资源,关闭连接 等 , 封装起来

package util;import com.mysql.cj.jdbc.MysqlDataSource;
import com.mysql.cj.xdevapi.Collection;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/bit_1027?characterEncoding=utf8" +"&allowPublicKeyRetrieval=true&useSSL=false";//用户名private static final String USER = "root";//密码private static final String PASSWORD = "119856";//当类加载到JVM时 , 执行数据源的初始化static {MysqlDataSource mysqlDataSource = new MysqlDataSource();mysqlDataSource.setURL(URL);mysqlDataSource.setUser(USER);mysqlDataSource.setPassword(PASSWORD);dataSource = mysqlDataSource;}//构造方法私有化 ,防止new这个对象private DBUtil() {}//获取数据库连接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) {e.printStackTrace();}}if (statement != null) {try {statement.close();} catch (SQLException e) {e.printStackTrace();}}if (connection != null) {try {connection.close();} catch (SQLException e) {e.printStackTrace();}}}
}

示例 : 执行一条插入语句

import util.DBUtil;import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Scanner;public class insertTest1 {public static void main(String[] args) {Connection connection = null;PreparedStatement statement= null;//插入语句不需要定义结果集 (insert返回的是受影响的行数)try {// 1.获取数据库连接connection = DBUtil.getConnection();// 2.定义SQL语句String sql = "insert into students(name,gender,age,class_id) values (?,?,?,?);";// 3.定义SQL预处理对象statement = connection.prepareStatement(sql);// 4.接收用户参数System.out.println("请输入姓名");Scanner scanner = new Scanner(System.in);String name = scanner.next();System.out.println("请输入性别");String gender = scanner.next();System.out.println("请输入年龄");Integer age = Integer.valueOf(scanner.next());System.out.println("请输入班级");Integer class_id = Integer.valueOf(scanner.next());// 5.用真实数据填充占位符statement.setString(1,name);statement.setString(2,gender);statement.setInt(3,age);statement.setInt(4,class_id);// 执行插入操作并获取受影响行数int rows = statement.executeUpdate();System.out.println("插入成功,受影响行数:" + rows);} catch (SQLException e) {e.printStackTrace();}finally {//释放资源,关闭连接DBUtil.close(null,statement,connection);}}
}
http://www.dtcms.com/a/561366.html

相关文章:

  • 从零开始学习Redis(六):Redis最佳实践(使用经验总结)
  • 秦皇岛建设网站西安百度seo代理
  • 备案 几个网站职业生涯规划
  • Ruby CGI Cookie 使用指南
  • 网站建设重要意义西部数码做跳转网站
  • X-plore安卓版(安卓手机文件管理器)
  • 【自然语言处理】基于生成式语言模型GPT
  • 广州网站建设方案案例用ps做网站画布一般建多大
  • 兰州网站搜索排名中国苏州网站
  • 【第二十周】自然语言处理的学习笔记05
  • 集成测试的分类
  • 上海网站建设百度推广公司wordpress 暂停前台访问
  • 微信网站建设哪家好企业网站分类举例
  • PyTorch 中 model.eval() 的使用与作用详解
  • Linux文件搜索:grep、find命令实战应用(附案例)
  • 搞一个卖东西的网站怎么做企业形象设计英文
  • WebStorm Deployment 实战:一键实时同步到腾讯云 ECS
  • 《深入理解 Python asyncio 事件循环:原理剖析、实战案例与最佳实践》
  • 网络安全事故响应全流程详解
  • 深圳 微网站建设ydgcm网络推广竞价
  • 中文网站 可以做谷歌推广吗制作一个网站数据库怎么做的
  • 【技术指南】打造个人Z-Library镜像:从架构解析到可持续运维
  • 广州最大网站建设做数字艺术设计的网站
  • StarRocks 4.0:基于 Apache Iceberg 的 Catalog 中心化访问控制
  • MySQL下载安装配置(超级超级入门级)
  • 如何制作一个简单的网站在线制作图片书
  • 十三、JS进阶(二)
  • bfs/dfs-最大连通问题
  • 找考卷做要去哪个网站百度推广app怎么收费
  • Matlab自学笔记六十七:(编程实例)非线性方程组求解fsolve