【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();

但这种写法后续会使得MysqlDataSource类名扩散到代码其他地方;

向上转型+向下转型的写法可以使MysqlDataSource类名不会扩散到代码的其他地方,后续如果需要修改数据库为别的数据库,代码改动比较小,即mysql与程序之间的耦合较低;

二种方式均可使用;

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

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

① jdbc:mysql表示:此url用于给jdbc操作mysql数据库使用的,如果使用其他数据库如Oracle则写为:jdbc:oracle;

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

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

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

⑤ 在URL中?表示访问资源时需要的参数;

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

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

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

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

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

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

执行SQL或操作数据库中出现问题,一般都会抛出SQLException异常;

(3)注意区别连接(Connection)与链接(Link):

连接:进行网络通信双方的抽象关系;

链接:快捷方式;

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语句进行预编译,对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);

两个参数,第一个数字表示对应的问号的序号,从1开始计数:

分别表示将第一个占位符替换为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("xxxxx");// 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.hqwc.cn/news/471955.html

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

相关文章

牛腩新闻发布系统总结

目录 背景: 过程: 总结: 背景: 对于看牛腩视频都是每天坐立不安的事情,生怕看着看着遇到代码问题,那样自己又得需要费很大力气去解决,所以进展缓慢,之前也听过墨菲定律得书,如果不想出错的事情,那就一定…

《VulnHub》GoldenEye:1

title: 《VulnHub》GoldenEye:1 date: 2024-02-16 14:53:49 updated: 2024-02-16 15:08:49 categories: WriteUp:Cyber-Range excerpt: 主机发现、目标信息扫描、源码 js 文件泄露敏感信息、hydra 爆破邮件服务(pop3)、邮件泄露敏…

微信小程序框架阐述

目录 一、框架 响应的数据绑定 页面管理 基础组件 丰富的 API 二、逻辑层 App Service 小程序的生命周期 注册页面 使用 Page 构造器注册页面 在页面中使用 behaviors 使用 Component 构造器构造页面 页面的生命周期 页面路由 页面栈 路由方式 注意事项 模块化…

面试经典150题——最小覆盖子串(困难)

"The greatest glory in living lies not in never falling, but in rising every time we fall." - Nelson Mandela​ 1. 题目描述 2. 题目分析与解析 2.1 思路一——暴力求解 还是和之前讲的一样,看见题目没思路,先试试普通情况下人的解法…

输入输出自定义映射矩阵(数据结构树)

输出自定义FC其它算法实现,可以参考下面文章: https://rxxw-control.blog.csdn.net/article/details/125994252https://rxxw-control.blog.csdn.net/article/details/125994252下面我们看下我们的控制要求。在学习本篇博客之前大家可以熟悉下数据结构图…

Qt Creator 继承分文件编写代码流程实现简单案列

Qt Creator 继承分文件流程实现简单案列 打开Qt Creator&#xff0c;新建c项目 添加类 完成之后&#xff0c;会自动生成.h和.cpp文件 一、animal.h文件 主要用来写类&#xff0c;包括成员变量和函数 #ifndef ANIMAL_H #define ANIMAL_H #include <iostream> #inclu…

牛客网SQL进阶123:高难度试卷的得分的截断平均值

官网链接&#xff1a; SQL类别高难度试卷得分的截断平均值_牛客题霸_牛客网牛客的运营同学想要查看大家在SQL类别中高难度试卷的得分情况。 请你帮她从exam_。题目来自【牛客题霸】https://www.nowcoder.com/practice/a690f76a718242fd80757115d305be45?tpId240&tqId2180…

挑战杯 python的搜索引擎系统设计与实现

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; python的搜索引擎系统设计与实现 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;3分工作量&#xff1a;5分创新点&#xff1a;3分 该项目较为新颖&#xff…

SpringCloud之Feign发送Http请求

文章目录 http客户端Feign使用步骤自定义Feign的配置Feign的性能优化Feign的性能优化-连接池配置 Feign的最佳实践 http客户端Feign Feign的介绍&#xff1a; Feign是一个声明式的http客户端&#xff0c;官方地址&#xff1a;https:/github.com/OpenFeign/feign 其作用就是帮助…

函数递归与迭代附n的阶乘+顺序打印一个整数的每一位数+求第n个斐波那契数

1. 什么是递归&#xff1f; 递归其实是一种解决问题的方法&#xff0c;在C语言中&#xff0c;递归就是函数自己调用自己。 下面是一个最简单的C语言递归代码&#xff1a; #include <stdio.h> int main() {printf("hehe\n");main();//main函数中⼜调⽤了main函数…

多线程面试题汇总

多线程面试题汇总 一、多线程1、线程的生命周期2、线程的创建&#xff08;函数创建&#xff09;3、线程的创建&#xff08;使用类&#xff09;4、守护线程 二、全局解释器锁1、使用单线程实现累加到5000000002、使用多线程实现累加到5000000003、总结 三、线程安全1、多线程之数…

Fiddler抓包(网页、手机、MUMU模拟器)

前置条件&#xff1a;电脑上下载安装好了Fiddler&#xff0c;有浏览器 一、网页抓包 1、fiddler下载安装证书 Tools-Options 勾选下面两个框 点击下面的选项&#xff0c;信任证书 会弹出弹窗&#xff0c;点击yes&#xff08;这个时候注意&#xff0c;DO_NOT_TRUST_FiddlerRo…