【MySQL】_JDBC

目录

1. JDBC原理

2. 导入JDBC驱动包

3. 编写JDBC代码实现Insert

3.1 创建并初始化一个数据源

3.2 和数据库服务器建立连接

3.3 构造SQL语句

3.4 执行SQL语句

3.5 释放必要的资源

4. JDBC代码的优化

4.1 从控制台输入

4.2 避免SQL注入的SQL语句

5. 编写JDBC代码实现Select


1. JDBC原理

1. 各种数据库如MySQL、Oracle、SQLServer等,在开始时会提供一组编程接口(API),

API即application programming interface,即代码层次上的提供的功能,API往往是通过函数或类的形式来提供的。

2. 不同的数据库系统的API是不同的JDBC就是统一Java与数据库连接的一套规范的API:

3.Java程序员如果想要进行数据库开发,就需要在项目中导入对应数据库的驱动包,才能编写代码。

4. 驱动包是数据库厂商提供的,此处以MySQL为例,获取方式有:

(1)从MySQL官网获取(现为Oracle官网的一个子网);

(2)github;

(3)maven中央仓库;

注:中央仓库可以理解为一个服务器,托管了各种软件程序包,maven就类似于应用商店,通过应用商店就可以访问到应用程序包并进行下载;

2. 导入JDBC驱动包

3. 编写JDBC代码实现Insert

import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;public class JDBCInsert {public static void main(String[] args) throws SQLException {// 1. 创建并初始化一个数据源;DataSource dataSource = new MysqlDataSource();// 把dataSource对象转为MysqlDataSource类型// setUrl是MysqlDataSource类的方法要调用需先将对象转为MysqlDataSource类型((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/JDBCProgram?characterEncoding=utf8&useSSL=false");((MysqlDataSource)dataSource).setUser("root");((MysqlDataSource)dataSource).setPassword("xxxxx");// 2. 和数据库服务器建立连接;Connection connection =  dataSource.getConnection();// 3. 构造 SQL 语句String sql = "insert into student values(1, 'Mike')";// 使用PreparedStatement对sql语句进行预编译PreparedStatement statement = connection.prepareStatement(sql);// 4. 执行 SQL 语句int ret = statement.executeUpdate();System.out.println("ret = "+ ret);// 5. 释放必要的资源statement.close();connection.close();}
}

 运行代码,在idea控制台有:

并在MySQL中查看Student表结果:

mysql> select* from student;
+------+------+
| id   | name |
+------+------+
|    1 | Mike |
+------+------+
1 row in set (0.00 sec)

编写JDBC代码需要以下五个步骤:

3.1 创建并初始化一个数据源

(1)数据源即数据的源头,此处数据来源于数据库,即此处要描述数据库服务器在哪里;

数据库中使用DataSourse接口进行描述;

(2)在创建并初始化一个数据源,也可以无需向上转型+向下转型,直接使用MysqlDataSource:

MysqlDataSource dataSource = new MysqlDataSource();

只是在向上转型+向下转型的写法比较流行,二者均可使用;

(3)URL即唯一资源定位符,用于描述网络上某个资源所在的位置,此处设置为:

((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/JDBCProgram?characterEncoding=utf8&useSSL=false");

① jdbc是固定的,mysql为连接的哪一个库;

② 127.0.0.1为本地回环地址,表示本主机;

③ 3306为数据库服务器默认端口号,标记某一主机上的进程;

④ JDBCProgram为数据库名(自行创建);

⑤ characterEncoding=utf8&useSSL=false分别表示字符集为utf8和不加密,SSL是一个加密协议;

(3)除设置URL之外,还需设置User和Passward才能访问数据库服务器,用户名默认为root,密码为安装数据库时的密码;

(4)经过第一步后,只是描述了数据库的位置与用户名、密码等,还没有进行连接;

3.2 和数据库服务器建立连接

(1)使用getConnection方法与数据库服务器建立连接,并用Connection类型的变量来接受返回值,注意选择第一个jdbc的Connection:

(2)如果getConnection方法正常运行则连接建立成功,如果连接建立失败会直接抛异常;

3.3 构造SQL语句

基于以下数据库与数据表:

mysql> use jdbcprogram
Database changed
mysql> show tables;
+-----------------------+
| Tables_in_jdbcprogram |
+-----------------------+
| student               |
+-----------------------+
1 row in set (0.00 sec)mysql> desc student;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | YES  |     | NULL    |       |
| name  | varchar(20) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

 (1)构造的SQL语句与在MySQL中构造的规定相同;

(2)如果请求是个SQL字符串,服务器是可以处理的。服务器就需要对SQL进行解析。

客户端数目庞大时会导致服务器压力很大,故而在客户端使用PreparedStatement对SQL语句进行预编译,就可以减轻服务器的压力;

3.4 执行SQL语句

(1)注意SQL语句的insert、delete和update操作都是使用executeUpdate方法进行执行的,返回值是int类型数据,表示影响的行数;

(2)select操作使用的是executeQuery方法

3.5 释放必要的资源

(1)数据库的客户端与服务器进行通信时,会消耗一定的系统资源,如CPU、内存、硬盘、带宽等等。为了防止服务器同时处理多个客户端造成系统资源受限,当客户端不使用服务器时,就对资源进行释放;

(2)语句与连接均需要释放,需要先释放语句再释放连接

释放的顺序与创建的顺序是相反的

(3)除Datsource之外,还有一种DriverManager的写法,这种写法是通过反射的方式加载驱动包中的类,进一步进行后续操作的。

但并不建议使用这种写法,反射属于java开发的特殊手段,其代码可读性非常差,编译期难以对代码的正确性进行检查,容易产生运行时异常,建议不到万不得已不要使用反射;

并且DataSource内置了数据库连接池,可以复用连接,提高连接服务器的效率;

4. JDBC代码的优化

对于上文的JDBC代码,要插入的数据是硬编码,但是让用户编码是不现实的,故而需要将数据通过其他方式供用户输入。

4.1 从控制台输入

import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Scanner;public class JDBCInsert {public static void main(String[] args) throws SQLException {Scanner scanner = new Scanner(System.in);// 1. 创建并初始化一个数据源;DataSource dataSource = new MysqlDataSource();((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/JDBCProgram?characterEncoding=utf8&useSSL=false");((MysqlDataSource)dataSource).setUser("root");((MysqlDataSource)dataSource).setPassword("xxxxx");// 2. 和数据库服务器建立连接;Connection connection =  dataSource.getConnection();// 3. 从控制台读取用户输入的内容System.out.println("请输入学生姓名:");String name = scanner.next();System.out.println("请输入学生学号:");int id = scanner.nextInt();// 4. 构造 SQL 语句String sql = "insert into student values(" + id + ", '"+name + "')";// 预编译PreparedStatement statement = connection.prepareStatement(sql);// 5. 执行 SQL 语句int ret = statement.executeUpdate();System.out.println("ret = "+ ret);// 6. 释放必要的资源statement.close();connection.close();}
}

运行代码,在控制台输入一下信息: 

在mysql中查看Student表:

mysql> select* from student;
+------+------+
| id   | name |
+------+------+
|    1 | Mike |
|    2 | Mary |
+------+------+
2 rows in set (0.00 sec)

4.2 避免SQL注入的SQL语句

在上例代码中,构造的SQL语句为:

String sql = "insert into student values(" + id + ", '"+name + "')";

如果用户输入的name形如:王五');select* from ***,导致看似一条SQL语句变为多个语句,就会出现SQL注入问题,如果再携带drop database之类的语句,可能会对系统造成更大的伤害。

针对以上问题,可以借助PreparedStatement的拼装功能实现:

import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Scanner;public class JDBCInsert {public static void main(String[] args) throws SQLException {Scanner scanner = new Scanner(System.in);// 1. 创建并初始化一个数据源;DataSource dataSource = new MysqlDataSource();// 把dataSource对象转为MysqlDataSource类型// setUrl是MysqlDataSource类的方法要调用需先将对象转为MysqlDataSource类型((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/JDBCProgram?characterEncoding=utf8&useSSL=false");((MysqlDataSource)dataSource).setUser("root");((MysqlDataSource)dataSource).setPassword("xxxxx");// 2. 和数据库服务器建立连接;Connection connection =  dataSource.getConnection();// 3. 从控制台读取用户输入的内容System.out.println("请输入学生姓名:");String name = scanner.next();System.out.println("请输入学生学号:");int id = scanner.nextInt();// 4. 构造 SQL 语句String sql = "insert into student values(?, ?)";// 使用PreparedStatement对sql语句进行预编译PreparedStatement statement = connection.prepareStatement(sql);statement.setInt(1, id);statement.setString(2, name);// 打印statement需在拼接数据之后System.out.println(statement);// 5. 执行 SQL 语句int ret = statement.executeUpdate();System.out.println("ret = "+ ret);// 6. 释放必要的资源statement.close();connection.close();}
}

输入学生姓名与学号后,控制台输出结果如下:

在mysql中查看Student表:

mysql> select* from student;
+------+------+
| id   | name |
+------+------+
|    1 | Mike |
|    2 | Mary |
|    3 | John |
+------+------+
3 rows in set (0.00 sec)

注:(1)构造的SQL语句中的2个?是两个占位符,statement.setInt与statement.setString方法就可以把占位符替换为指定的值,

        statement.setInt(1, id);statement.setString(2, name);

分别表示将第一个占位符替换为id的值,第二个占位符替换为name的值,当用户输入给id和name赋值后,就会通过该方法自动替换;

(2)可以使用打印statement的方法查看具体拼接情况,需将该语句置于拼接数据之后;

假如代码执行出错了也可以把statement打印出来查看具体语法是否出错;

5. 编写JDBC代码实现Select

import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;public class JDBCSelect {public static void main(String[] args) throws SQLException {// 1. 创建并初始化数据源DataSource dataSource = new MysqlDataSource();((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/JDBCProgram?characterEncoding=utf8&useSSL=false");((MysqlDataSource)dataSource).setUser("root");((MysqlDataSource)dataSource).setPassword("97805");// 2. 建立连接Connection connection = dataSource.getConnection();// 3. 构造SQL语句String sql = "select* from Student";PreparedStatement statement = connection.prepareStatement(sql);// 4. 执行SQL语句ResultSet resultSet = statement.executeQuery();// 5. 遍历结果集合while(resultSet.next()){int id = resultSet.getInt("id");String name = resultSet.getString("name");System.out.println("id = " + id +", name = " + name);}// 6. 释放资源resultSet.close();statement.close();connection.close();}
}

控制台输出结果为:

 

注:(1)执行SQL的语句为:

ResultSet resultSet = statement.executeQuery();

对比SQL实现Insert的executeUpdate方法返回的是一个int类型数据,实现Select的executeQuery方法返回的是一个ResultSet类型对象

该对象可以视为是一张表,初始时光标指向表首行,可以使用getXXX方法获取当前光标指向的行的数据。每调用一次next,就使光标下移一行,当光标遍历完整张表,再调用next时,就会返回false;

(2)getXXX方法用于取出这一行指定列的值,使用的方法要与列的类型匹配

参数可以是第几列的下标,也可以是列名,更推荐使用列名

        while(resultSet.next()){int id = resultSet.getInt("id");String name = resultSet.getString("name");System.out.println("id = " + id +", name = " + name);}

(3)实现Select的程序在释放资源时,相较于Insert,需要多释放一个resultSet,可以将查询结果的临时表视为一个resultSet;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/149930.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

〖大前端 - 基础入门三大核心之JS篇㊲〗- DOM改变元素节点的css样式、HTML属性

说明:该文属于 大前端全栈架构白宝书专栏,目前阶段免费,如需要项目实战或者是体系化资源,文末名片加V!作者:不渴望力量的哈士奇(哈哥),十余年工作经验, 从事过全栈研发、产品经理等工作&#xf…

Python数据分析实战① Python实现数据可视化

文章目录 一、数据可视化介绍二、matplotlib和pandas画图1.matplotlib简介和简单使用2.matplotlib常见作图类型3.使用pandas画图4.pandas中绘图与matplotlib结合使用 三、订单数据分析展示四、Titanic灾难数据分析显示 一、数据可视化介绍 数据可视化是指将数据放在可视环境中…

.Net中Redis的基本使用

前言 Redis可以用来存储、缓存和消息传递。它具有高性能、持久化、高可用性、扩展性和灵活性等特点,尤其适用于处理高并发业务和大量数据量的系统,它支持多种数据结构,如字符串、哈希表、列表、集合、有序集合等。 Redis的使用 安装包Ser…

wpf devexpress 排序、分组、过滤数据

这个教程示范在GridControl如何排序数据,分组数据给一个行创建一个过滤。这个教程基于前一个教程。 排序数据 可以使用GridControl 排序数据。这个例子如下过滤数据对于Order Date 和 Customer Id 行: 1、对于Order Date 和 Customer Id 行指定Colum…

Linux虚拟机中网络连接的三种方式

Linux 虚拟机中网络连接的三种方式 先假设一个场景,在教室中有三个人:张三、李四和王五(这三个人每人有一台主机),他们三个同处于一个网段中(192.169.0.XX),也就是说他们三个之间可…

深度学习_13_YOLO_图片切片及维度复原

需求: 在对获取的图片进行识别的时候,如果想减少不必要因素的干扰,将图片切割只对有更多特征信息的部分带入模型识别,而剩余有较多干扰因素的部分舍弃,这就是图片切割的目的,但是又由于模型对图片的维度有较…

Spring Cloud学习(十)【Elasticsearch搜索功能 分布式搜索引擎02】

文章目录 DSL查询文档DSL查询分类全文检索查询精准查询地理坐标查询组合查询相关性算分Function Score Query复合查询 Boolean Query 搜索结果处理排序分页高亮 RestClient查询文档快速入门match查询精确查询复合查询排序、分页、高亮 黑马旅游案例 DSL查询文档 DSL查询分类 …

QT day3作业

1.思维导图 2、 完善对话框,点击登录对话框,如果账号和密码匹配,则弹出信息对话框,给出提示”登录成功“,提供一个Ok按钮,用户点击Ok后,关闭登录界面,跳转到其他界面 如果账号和密…

不懂找伦敦银趋势?3个方法搞定

趋势是我们的朋友,但是这个朋友却很喜欢跟我们开玩笑,如果我们不留意,根本发觉不了它的存在。怎么找到趋势本体并且和它做个好朋友呢?下面我们就来介绍三个方法。 数波段的高点和低点。我们以当前的市场波动价格为轴,向…

IDEA中更换java项目JDK

我们打开IDEA 打开项目 然后选择 File 下的 Project Structure 这里 我们下拉选择自己需要的JDK Sources这里 也要设置一下JDK对应版本 然后 上面这个 Project 中 也要设置一下对应jdk的版本 保持一直 然后 我们打开 File 下的 Settings 然后 找到如下图配置 如果JKD版本看…

深度学习人体语义分割在弹幕防遮挡上的实现 - python 计算机竞赛

文章目录 1 前言1 课题背景2 技术原理和方法2.1基本原理2.2 技术选型和方法 3 实例分割4 实现效果5 最后 1 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 深度学习人体语义分割在弹幕防遮挡上的应用 该项目较为新颖,适合作为竞…

Unity Meta Quest 一体机开发(七):配置玩家 Hand Grab 功能

文章目录 📕教程说明📕玩家物体配置 Hand Grab Interactor⭐添加 Hand Grab Interactor 物体⭐激活 Hand Grab Visual 和 Hand Grab Glow⭐更新 Best Hover Interactor Group 📕配置可抓取物体(无抓取手势)⭐刚体和碰撞…

DDPM的学习

Denoising Model 首先是宏观理解一下 Denoising Model 的输入 去噪很多步,用的是同一个Denoising Model,但是输入图片可能差距很大。解决方法:给Denoising Model多输入一个变量,表示现在的去噪阶段,让Denoising Mod…

解决requests 2.28.x版本SSL错误:证书验证失败

1、问题背景 在使用requests 2.28.1版本时,我进行HTTP post传输报告负载时,由于SSL验证设置为True,请求失败,错误如下:(Caused by SSLError(SSLCertVerificationError(1, ‘[SSL: CERTIFICATE_VERIFY_FAILED] certifi…

ChatGPT最强?文心一言与ChatGPT对比

对于同一个问题我们分别对文心一言3.5和ChatGPT3.5输出回答,结果如下图,可以看到文心一言的回答更好,文心一言是由百度开发的人工智能语言模型,它的中文理解能力主要是基于百度强大的搜索引擎和自然语言处理技术。文心一言更加注重…

mysql优化之explain 以及 索引优化

Mysql安装文档参考:https://blog.csdn.net/yougoule/article/details/56680952 Explain工具介绍 使用EXPLAIN关键字可以模拟优化器执行SQL语句,分析你的查询语句或是结构的性能瓶颈 在 select 语句之前增加 explain 关键字,MySQL 会在查询上设…

非关系型数据库Redis(缓存型数据库)

关系型数据库和非关系型数据库的区别 关系型数据库 是一个结构化的数据库,记录方式是行(记录对象属性)和列(声明对象) 表与表之间是有关联的,使用sql语句来对指定的表、库进行增删改查 在创建表的时候&…

hive sql 行列转换 开窗函数 炸裂函数

hive sql 行列转换 开窗函数 炸裂函数 准备原始数据集 学生表 student.csv 讲师表 teacher.csv 课程表 course.csv 分数表 score.csv 员工表 emp.csv 雇员表 employee.csv 电影表 movie.txt 学生表 student.csv 001,彭于晏,1995-05-16,男 002,胡歌,1994-03-20,男 003,周杰伦,…

Flutter 中数据存储的四种方式

在 Flutter 中,存储是指用于本地和远程存储和管理数据的机制。以下是 Flutter 中不同存储选项的概述和示例。 Shared Preferences(本地键值存储) Shared Preferences 是一种在本地存储少量数据(例如用户首选项或设置&#xff09…

buildadmin+tp8表格操作(7.1)表格的事件监听(el-table中的事件)

因为buildAdmin是封装的 el-table的组件,所以el-table中的事件, 也是可以使用的, 两者有几个事件是有共同的(比如 双击事件), 这时可以根据自己的需要自行选择 以下代码是 buildadmin 使用 el-table中的事…