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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

深入Ansible

1.什么是ansible ansible是新出现的自动化运维工具,基于Python开发,集合了众多运维工具(puppet、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。 ansible是基于 paramiko 开发的…

11月20日星期一今日早报简报微语报早读

11月20日星期一,农历十月初八,早报微语早读。 1、T1以3-0横扫WBG,拿下S13冠军!Faker豪取第4冠; 2、天舟七号货运飞船已运抵文昌发射场,将于明年初发射; 3、“中韩之战”球票已经售罄&#xf…

没收到Win11 23H2正式版的推送怎么升级到23H2

没收到Win11 23H2正式版的推送怎么升级到23H2?用户反映自己没有收到Win11 23H2正式版的更新推送,又想升级为23H2版本。接下来小编给大家详细介绍不同的升级方法,帮助更多的用户完成Win11 23H2系统的更新,升级后就能体验到Win11 23…

解锁安全与信任的双重礼遇!JoySSL证书买二送一,买三送二

JoySSL是业内领先的SSL证书提供商,致力于为网站提供最高水平的安全性。通过使用JoySSL证书,您的网站将获得强大的加密保护,确保用户的敏感信息在传输过程中得到安全加密,有效地抵御各种网络威胁。 为何选择JoySSL证书&#xff1f…

解决龙芯loongarch64服务器编译安装Python后yum命令无法使用的问题“no module named ‘dnf‘”

引言 在使用Linux系统时,我们经常会使用yum来管理软件包。然而,有时候我们可能会遇到yum不可用的情况,其中一个原因就是Python的问题。本文将介绍Python对yum可用性的影响,并提供解决方案。 问题引发 正常情况下,安装linux系统后,yum命令是可用状态,升级Python版本后,…

pyqt5切换到pyqt6遇到问题

pyqt5切换到pyqt6变更点 FramelessWindowHint Qt.FramelessWindowHint Qt.WindowType.FramelessWindowHint globalPos event.globalPos() event.globalPosition() LeftButton Qt.LeftButton Qt.MouseButton.LeftButton StrongFocus Qt.StrongFocus Qt.FocusPolicy.Stro…

装备中国功勋企业——兰石重装,建设LTC全流程管理|基于得帆云低代码的CRM案例系列

兰石重型装备股份有限公司 兰石重型装备股份有限公司(以下简称“兰石重装”)成立于2001年,经营范围为炼油、化工、核电等能源领域所需的装备的设计、制造、安装、成套与服务;工程项目建设与服务;机械加工;检…

第94步 深度学习图像分割:DeepLabv3建模

基于WIN10的64位系统演示 一、写在前面 本期,我们继续学习深度学习图像分割系列的最后一个模型,DeepLabv3。 二、DeepLabv3简介 DeepLabv3 是 DeepLab 系列中的第三个版本,以其高准确性和能够在多个尺度上识别物体轮廓而著称。 以下是 De…

在建筑设计方面3DMax和Maya哪一个更好?

对于建筑设计可视化工具,有许多渲染程序提供了一套非常复杂的工具,使专业人员能够做到最好。ArchViz工具对建筑师和设计师来说非常重要,因为它们可以让他们更准确地识别设计发展阶段的问题,并更有效地与客户交流设计理念。 在今天…

自动化测试开发 —— 如何封装自动化测试框架?

封装自动化测试框架,测试人员不用关注框架的底层实现,根据指定的规则进行测试用例的创建、执行即可,这样就降低了自动化测试门槛,能解放出更多的人力去做更深入的测试工作。本篇文章就来介绍下,如何封装自动化测试框架…

图片OCR转表格:终极攻略,优缺点全解析

随着人工智能技术的不断发展,图片OCR识别已经成为了许多领域中不可或缺的一部分。将图片中的文字识别并转化为文本,可以大大提高数据处理的效率和准确性。而将图片中的表格识别并转化为可编辑的表格格式,则可以更加方便地对数据进行处理和分析…

Iris for Mac:简单易用的录屏神器,让你的演示更出色

你是否曾需要在Mac上进行屏幕录制,但却苦于找不到一款简单易用的工具?那么,今天我们将为你介绍一款全新的屏幕录制软件——Iris for Mac。这款软件不仅功能强大,而且操作简单,可以轻松满足你的各种录屏需求。 一、简单…

auth 对象创建 session 时出现 异常 详细解析

在使用 requests 库的 1.0.3 版本时,尝试使用 auth 对象创建 session 时出现了 TypeError 异常。然而,在 0.14.2 版本中,这个操作是正常工作的。下面是具体的错误信息: python import requests requests.version 1.0.3 auth re…

Leetcode—53.最大子数组和【中等】

2023每日刷题&#xff08;三十四&#xff09; Leetcode—53.最大子数组和 前缀和算法思想 参考灵茶山艾府 实现代码 #define MAX(a, b) ((a > b) ? (a) : (b)) #define MIN(a, b) ((a < b) ? (a) : (b)) int maxSubArray(int* nums, int numsSize) {int ans INT_…

27岁想转行IT,还来得及吗?

“种一棵树最好的时间是十年前&#xff0c;其次是现在&#xff01; ” 任何时候&#xff0c;只要开始&#xff0c;一切都来得及&#xff0c;如果你真的想要转行&#xff0c;何时都不会晚&#xff0c;只要你付出相应的努力&#xff0c;坚持下去&#xff0c;一切都会朝着自己希望…

easyExcel注解详情

前言11个注解字段注解 类注解基础综合示例补充颜色总结 11个注解 ExcelProperty ColumnWith 列宽 ContentFontStyle 文本字体样式 ContentLoopMerge 文本合并 ContentRowHeight 文本行高度 ContentStyle 文本样式 HeadFontStyle 标题字体样式 HeadRowHeight 标题高度 HeadStyle…

深入浅出讲解python闭包

一、定义 在 Python 中&#xff0c;当一个函数内部定义的函数引用了外部函数的局部变量时&#xff0c;就形成了一个闭包。这个内部函数可以访问并修改外部函数的局部变量&#xff0c;而这些局部变量的状态会一直被保存在闭包中&#xff0c;即使外部函数已经执行完毕。 这种机…

在python中分别利用numpy,tensorflow,pytorch实现数据的增加维度(升维),减少维度(降维)

文章目录 前言一、使用numpy实现升维度&#xff0c;降维度二、使用TensorFlow实现升维度&#xff0c;降维度三、使用PyTorch实现升维度&#xff0c;降维度总结 前言 我们明确一下升维和降维的概念&#xff1a; 升维&#xff08;Dimensionality Augmentation&#xff09;&…

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

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

通达信的ebk文件

我们在通达信软件中 调出 “自定义板块设置” 这个菜单&#xff0c;点击“导出”&#xff0c;会提示你存储 “自选股.EBK”&#xff0c;其实就是对自定义板块里的目录进行备份的一种方式&#xff0c; 当我们打开 这个文件&#xff0c;你会发现其实就是存储了 股票代码&#xff…