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.xdnf.cn/news/1542785.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【笔记】材料分析测试:晶体学

晶体与晶体结构Crystal and Crystal Structure 1.晶体主要特征 固态物质可以分为晶态和非晶态两大类,分别称为晶体和非晶体。 晶体和非晶体在微观结构上的区别在于是否具有长程有序。 晶体(长程有序)非晶(短程有序&#xff09…

机器人机构、制造

简单整理一下,在学习了一些运动学和动力学之类的东西,简单的整合了一些常用的机械结构和图片。 1.电机: 市面上的电机有:直流电机,交流电机,舵机,步进电机,电缸,无刷电…

李宏毅结构化学习 03

文章目录 一、Sequence Labeling 问题概述二、Hidden Markov Model(HMM)三、Conditional Random Field(CRF)四、Structured Perceptron/SVM五、Towards Deep Learning 一、Sequence Labeling 问题概述 二、Hidden Markov Model(HMM) 上图 training data 中的黑色字为x&#xff…

基于单片机的水位检测系统仿真

目录 一、主要功能 二、硬件资源 三、程序编程 四、实现现象 一、主要功能 基于51单片机,DHT11温湿度检测,水位检测,通过LCD1602显示,超过阈值报警,继电器驱动电机转动。通过矩阵按键切换选择设置各项参数阈值。 …

【Linux】通过内核以太层可查看应用程序运行时访问外网情况

比如,SourceInsight3.exe从外网接收信息: 下边是运行firefox时内核打印的日志,可以看到浏览器运行时调用了很多的操作系统内核系统调用,比如:文件读写、网络数据包的收发等等,其实这些日志还并不全&#x…

基于Ambari搭建hadoop生态圈+Centos7安装教程(还没写完,等明天补充完整)

当我们学习搭建hadoop的时候,未免也会遇见很多繁琐的事情,比如很多错误,需要解决。在以后公司,也不可能让你一个一个搭建hadoop,成千上万的电脑,你再一个个搭建,一个个报错,而且每台…

数据处理与统计分析篇-day08-apply()自定义函数与分组操作

一. 自定义函数 概述 当Pandas自带的API不能满足需求, 例如: 我们需要遍历的对Series中的每一条数据/DataFrame中的一列或一行数据做相同的自定义处理, 就可以使用Apply自定义函数 apply函数可以接收一个自定义函数, 可以将Series对象的逐个值或DataFrame的行/列数据传递给自…

K8s 之微服务的定义及详细资源调用案例

什么是微服务 用控制器来完成集群的工作负载,那么应用如何暴漏出去? 需要通过微服务暴漏出去后才能被访问 Service是一组提供相同服务的Pod对外开放的接口。借助Service,应用可以实现服务发现和负载均衡。service默认只支持4层负载均衡能力&…

OpenCV特征检测(10)检测图像中直线的函数HoughLinesP()的使用

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在二值图像中使用概率霍夫变换查找线段。 该函数实现了用于直线检测的概率霍夫变换算法,该算法在文献 181中有所描述。 HoughLines…

JavaEE: 深入探索TCP网络编程的奇妙世界(五)

文章目录 TCP核心机制TCP核心机制六: 拥塞控制为什么要有拥塞控制?动态调整的拥塞控制拥塞控制中,窗口大小具体的变化过程 TCP核心机制七: 延时应答TCP核心机制八: 捎带应答 TCP核心机制 前一篇文章 JavaEE: 深入探索TCP网络编程的奇妙世界(四) 书接上文~ TCP核心机制六: 拥…

Parallels Desktop 20 for Mac 推出:完美兼容 macOS Sequoia 与 Win11 24H2

Parallels Desktop 20 for Mac 近日正式发布,这一新版本不仅全面支持 macOS Sequoia 和 Windows 11 24H2,还在企业版中引入了一个全新的管理门户。新版本针对 Windows、macOS 和 Linux 虚拟机进行了多项改进,其中最引人注目的当属 Parallels …

Python 入门(一、使用 VSCode 开发 Python 环境搭建)

Python 入门第一课 ,环境搭建...... by 矜辰所致前言 现在不会 Python ,好像不那么合适,咱先不求精通,但也不能不会,话不多说,开干! 这是 Python 入门第一课,当然是做好准备工作&a…

计算机毕业设计 校园失物招领网站的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍:✌从事软件开发10年之余,专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ 🍅文末获取源码联系🍅 👇🏻 精…

嵌入式单片机STM32开发板详细制作过程--01

大家好,今天主要给大家分享一下,单片机开发板的制作过程,原理图的制作与PCB设计,以及电子元器件采购与焊接。 第一:单片机开发板成品展示 板子正面都有各个芯片的丝印与标号,方便焊接元器件的时候,可以参考。(焊接完成之后,成品图如下) 第二:开发板原理图制作 在制…

MATLAB中多张fig图合并为一个图

将下列两个图和为一个图 打开查看-----绘图浏览器 点击第一幅图中曲线右键复制,到第二幅图中粘贴即可完成

布草洗涤-酒店分楼层统计报表--———未来之窗行业应用跨平台架构

一、大酒店分层管理 1. 精准管理库存 - 能够清晰了解每个楼层布草的具体数量和状况,实现对布草库存的精细化管理,避免出现某些楼层布草短缺或过剩的情况。 2. 优化资源分配 - 依据各楼层的使用频率和需求差异,合理调配布草资源&…

排序--归并排序

1.什么是归并排序? 归并排序将待排序的数组分成两部分,对每部分递归地应用归并排序,然后将两个有序的子数组合并成一个有序的数组。这个过程一直重复,直到数组完全有序。归并排序的过程可以用一棵完全二叉树来形象地表示&#xf…

frpc内网穿透

官网地址:frp官网 本次用到的Liunx包: https://github.com/fatedier/frp/releases/download/v0.60.0/frp_0.60.0_linux_amd64.tar.gz下载: wget https://github.com/fatedier/frp/releases/download/v0.60.0/frp_0.60.0_linux_amd64.tar.g…

申论笔记杉树林

同义词尽量用文章中的词进行拼凑不一定要有前置词分条 单一题 同义词给分不一定需要前置词分条 1、2、3、尽量抄文章中的词,通顺即可,不一定要成句子不要过分关注形式 题干: 条理清晰:要求分条,尽量有提示词…

脱离枯燥的CRUD,灵活使用Mybatis,根据mybatis动态的xml片段和接口规范动态生成代理类,轻松应付简单业务场景。

需求 需求是这样的,我们有一个数据服务平台的产品,用户先将数据源信息保存到平台上,一个数据源可以提供多个接口服务,而每个接口服务在数据库中存一个具有mybatis语法的sql片段。这样的话,对于一些简单的业务只需要编…