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

Java-JDBC

JDBC

JDBC英文名为:Java Data Base Connectivity(Java数据库连接),官方解释它是Java编程语言和广泛的数据库之间独立于数据库的连接标准的Java API

根本上说JDBC是一种规范,它提供的接口,一套完整的,允许便捷式访问底层数据库。

不同的可执行文件都能通过JDBC访问数据库,又兼备存储的优势。

它就是Java与数据库的连接的桥梁或者插件,用Java代码就能操作数据库的增删改查、存储过程、事务等。

我们可以发现,JDK自带了一个java.sql包,而这里面就定义了大量的接口,不同类型的数据库,都可以通过实现此接口,编写适用于自己数据库的实现类。而不同的数据库厂商实现的这套标准,我们称为数据库驱动

使用JDBC连接数据库

6.0版本以上,不用手动加载驱动,我们直接使用即可

DriverManager就是管理我们的数据库驱动的

//1. 通过DriverManager来获得数据库连接
try (Connection connection = DriverManager.getConnection("连接URL","用户名","密码");//2. 创建一个用于执行SQL的Statement对象Statement statement = connection.createStatement()){   //注意前两步都放在try()中,因为在最后需要释放资源!//3. 执行SQL语句,并得到结果集ResultSet set = statement.executeQuery("select * from 表名");//4. 查看结果while (set.next()){...}
}catch (SQLException e){e.printStackTrace();
}
//5. 释放资源,try-with-resource语法会自动帮助我们close

了解Connection

Connection是数据库的连接对象,可以通过连接对象来创建一个Statement用于执行SQL语句:

Statement createStatement() throws SQLException;

PreparedStatement能够有效地预防SQL注入式攻击:

PreparedStatement prepareStatement(String sql)throws SQLException;

了解Statement

使用了executeQuery()方法来执行select语句,此方法返回给我们一个ResultSet对象,查询得到的数据,就存放在ResultSet中

Statement除了执行这样的DQL语句外,我们还可以使用executeUpdate()方法来执行一个DML或是DDL语句,它会返回一个int类型,表示执行后受影响的行数,可以通过它来判断DML语句是否执行成功

也可以通过excute()来执行任意的SQL语句,它会返回一个boolean来表示执行结果是一个ResultSet还是一个int,我们可以通过使用getResultSet()或是getUpdateCount()来获取

执行DQL操作

执行DQL操作会返回一个ResultSet对象,我们来看看如何从ResultSet中去获取数据:

//首先要明确,select返回的数据类似于一个excel表格
while (set.next()){//每调用一次next()就会向下移动一行,首次调用会移动到第一行
}

移动行数后,就可以通过set中提供的方法,来获取每一列的数据。

执行批处理操作

要执行很多条语句时,可以不用一次一次地提交,而是一口气全部交给数据库处理,这样会节省很多的时间。

public static void main(String[] args) throws ClassNotFoundException {try (Connection connection = DriverManager.getConnection();Statement statement = connection.createStatement()){statement.addBatch("insert into user values ('f', 1234)");statement.addBatch("insert into user values ('e', 1234)");   //添加每一条批处理语句statement.executeBatch();   //一起执行}catch (SQLException e){e.printStackTrace();}
}

将查询结果映射为对象

既然可以从数据库中获取数据了,那么现在就可以将这些数据转换为一个类来进行操作

首先定义我们的实体类:

public class Student {Integer sid;String name;String sex;public Student(Integer sid, String name, String sex) {this.sid = sid;this.name = name;this.sex = sex;}public void say(){System.out.println("我叫:"+name+",学号为:"+sid+",我的性别是:"+sex);}
}

进行一个转换:列的下标是从1开始的

while (set.next()){Student student = new Student(set.getInt(1), set.getString(2), set.getString(3));student.say();
}

也可以利用反射机制来将查询结果映射为对象,使用反射的好处是,无论什么类型都可以通过我们的方法来进行实体类型映射:

private static <T> T convert(ResultSet set, Class<T> clazz){try {Constructor<T> constructor = clazz.getConstructor(clazz.getConstructors()[0].getParameterTypes());   //默认获取第一个构造方法Class<?>[] param = constructor.getParameterTypes();  //获取参数列表Object[] object = new Object[param.length];  //存放参数for (int i = 0; i < param.length; i++) {   //是从1开始的object[i] = set.getObject(i+1);if(object[i].getClass() != param[i])throw new SQLException("错误的类型转换:"+object[i].getClass()+" -> "+param[i]);}return constructor.newInstance(object);} catch (ReflectiveOperationException | SQLException e) {e.printStackTrace();return null;}
}
while (set.next()){Student student = convert(set, Student.class);if(student != null) student.say();
}

SQL注入攻击

模拟登陆一个用户:

try (Connection connection = DriverManager.getConnection("URL","用户名","密码");Statement statement = connection.createStatement();Scanner scanner = new Scanner(System.in)){ResultSet res = statement.executeQuery("select * from user where username='"+scanner.nextLine()+"'and pwd='"+scanner.nextLine()+"';");while (res.next()){String username = res.getString(1);System.out.println(username+" 登陆成功!");}
}catch (SQLException e){e.printStackTrace();
}

如果我输入的是以下内容:

Test
1111' or 1=1; -- 
# Test 登陆成功!

原本的SQL语句会变为:

select * from user where username='Test' and pwd='1111' or 1=1; -- '

如果允许这样的数据插入,那么我们原有的SQL语句结构就遭到了破坏,使得用户能够随意登陆别人的账号。

因此我们可能需要限制用户的输入来防止用户输入一些SQL语句关键字,但是关键字非常多,这并不是解决问题的最好办法。

PreparedStatement

可以使用PreparedStatement来解决SQL注入攻击漏洞

public static void main(String[] args) throws ClassNotFoundException {try (Connection connection = DriverManager.getConnection("URL","用户名","密码");PreparedStatement statement = connection.prepareStatement("select * from user where username= ? and pwd=?;");Scanner scanner = new Scanner(System.in)){statement.setString(1, scanner.nextLine());statement.setString(2, scanner.nextLine());System.out.println(statement);    //打印查看一下最终执行的ResultSet res = statement.executeQuery();while (res.next()){String username = res.getString(1);System.out.println(username+" 登陆成功!");}}catch (SQLException e){e.printStackTrace();}
}

要提前给到PreparedStatement一个SQL语句,并且使用?作为占位符,它会预编译一个SQL语句,通过直接将我们的内容进行替换的方式来填写数据。

实际执行的SQL语句是什么:

com.mysql.cj.jdbc.ClientPreparedStatement: select * from user where username= 'Test' and pwd='123456'' or 1=1; -- ';

输入的参数一旦出现'时,会被变为转义形式\',而最外层有一个真正的'来将我们输入的内容进行包裹,因此它能够有效地防止SQL注入攻击

管理事务

JDBC默认的事务处理行为是自动提交;JDBC需要进行事务管理时,首先要通过Connection对象调用setAutoCommit(false) 方法, 将SQL语句的提交(commit)由驱动程序转交给应用程序负责

一旦关闭自动提交,那么现在执行所有的操作如果在最后不进行commit()来提交事务的话,那么所有的操作都会丢失

也可以使用rollback()来手动回滚之前的全部操作

con.setAutoCommit();   //关闭自动提交后相当于开启事务。
// SQL语句
// SQL语句
// SQL语句
con.commit();或 con.rollback();
public static void main(String[] args) throws ClassNotFoundException {try (Connection connection = DriverManager.getConnection("URL","用户名","密码");Statement statement = connection.createStatement()){connection.setAutoCommit(false);  //关闭自动提交,现在将变为我们手动提交statement.executeUpdate("insert into user values ('a', 1234)");statement.executeUpdate("insert into user values ('b', 1234)");statement.executeUpdate("insert into user values ('c', 1234)");connection.commit();   //如果前面任何操作出现异常,将不会执行commit(),之前的操作也就不会生效}catch (SQLException e){e.printStackTrace();}
}

创建一个回滚点来实现定点回滚:

public static void main(String[] args) throws ClassNotFoundException {try (Connection connection = DriverManager.getConnection("URL","用户名","密码");Statement statement = connection.createStatement()){connection.setAutoCommit(false);  //关闭自动提交,现在将变为我们手动提交statement.executeUpdate("insert into user values ('a', 1234)");Savepoint savepoint = connection.setSavepoint();   //创建回滚点statement.executeUpdate("insert into user values ('b', 1234)");connection.rollback(savepoint);   //回滚到回滚点,撤销前面全部操作statement.executeUpdate("insert into user values ('c', 1234)");connection.commit();   //提交事务(注意,回滚之前的内容都没了)}catch (SQLException e){e.printStackTrace();}
}

相关文章:

Java-JDBC

JDBC JDBC英文名为&#xff1a;Java Data Base Connectivity(Java数据库连接)&#xff0c;官方解释它是Java编程语言和广泛的数据库之间独立于数据库的连接标准的Java API 根本上说JDBC是一种规范&#xff0c;它提供的接口&#xff0c;一套完整的&#xff0c;允许便捷式访问底…...

【ROS】Nav2源码之nav2_planner详解

【ROS】郭老二博文之:ROS目录 1、简述 nav2_planner是路径规划器,把起始位置、姿势的信息输入nav2_planner模块,将会生成可行路径。 nav2_planner路径规划器和nav2_controller控制器相似,也使用插件的形式加载不同的路径规划器。 常用的路径规划器插件有: 1)NavFn Plan…...

mysql报SQLSTATE[22007]的错误的一个原因

最近在修改一个程序&#xff0c;打算将$video这个参数保存到数据库。修改的过程中出现错误。导致该程序不能发布新文章。在程序的一个db.php程序文件里使用var_dump($input, $stmt) ; 语句看到了错误信息&#xff0c;并找到了错误原因。信息里包含的错误代码是&#xff1a; SQ…...

Python —— UI自动化之 三大等待与三大切换

1、三大等待 1、硬性等待 1、概述 硬性等待也可以称之为强制等待&#xff0c;写法如下&#xff1a; time.sleep() 优点&#xff1a;使用简单 缺点&#xff1a;等待时间把握不准&#xff0c;容易造成时间浪费或者等待时间不足 2、实战 from time import sleep from sele…...

初识容器Docker

目前使用 Docker 基本上有两个选择&#xff1a;Docker Desktop和Docker Engine。Docker Desktop 是专门针对个人使用而设计的&#xff0c;支持 Mac 和 Windows 快速安装&#xff0c;具有直观的图形界面&#xff0c;还集成了许多周边工具&#xff0c;方便易用。 不是太推荐使用D…...

pikachu靶场搭建及通关

一、靶场搭建 下载工具&#xff1a;phpstudy Pikachu靶机下载地址&#xff1a; https://github.com/zhuifengshaonianhanlu/pikachu 下载后解压缩并放入如下文件夹&#xff08;网站根目录&#xff09; 建议修改文件名称为 pikachu 修改配置文件&#xff08;mysql 用户名&…...

选择排序(学习笔记)

选择排序 选择排序的基本思想是冒泡排序&#xff0c;记录当前位置i和最小值k的位置&#xff0c;使用一个变量j往后寻找。 每一轮找到最小值后与第一个元素进行交换&#xff0c;以此类推。 不使用辅助变量交换两个元素的值方法 package com.company.sort;import java.util.Ra…...

PCL 生成球形点云

目录 一、算法原理二、代码实现三、结果展示四、参考链接一、算法原理 生成球体点云的方法有很多种,Marsaglia于1972年提出了一个简单易行的实现方法,它从(-1,1)上的独立均匀分布中选取 x 1 x_1 x...

Flutter 剪裁(Clip)

&#x1f525; ClipOval &#x1f525; 子组件为正方形时剪裁成内贴圆形&#xff1b;为矩形时&#xff0c;剪裁成内贴椭圆 裁剪纯色背景 ClipOval(child: Container(width: 300.w,height: 300.w,decoration: const BoxDecoration(color: Colors.red),),), 裁剪背景图片 裁剪前…...

嵌入式C语言自我修养《GNU C编译器扩展语法》学习笔记

目录 一、C语言标准和编译器 二、指定初始化 三、宏构造“利器”&#xff1a;语句表达式 四、typeof与container_of宏 五、零长度数组 六、属性声明&#xff1a;section 七、属性声明&#xff1a;aligned 一、C语言标准和编译器 C语言标准的发展过程&#xff1a; ●…...

密码学二: md5 网站服务器与用户通信过程 ca原理 签名原理 Flame 病毒原理

md5被破解? MD5&#xff08;Message Digest Algorithm 5&#xff09;是一个较早的哈希函数&#xff0c;但由于其弱点和漏洞&#xff0c;它已经被认为不再适合用于安全性要求较高的应用。MD5的一些安全性问题包括&#xff1a; 碰撞攻击&#xff1a; MD5已经被证明容易受到碰撞攻…...

Zend Framework 3.1.3 gadget chain

前言 在推特上的PT SWARM账号发布了一条消息。 一个名为Zend Framework的php框架出现了新的gadget chain&#xff0c;可导致RCE。笔者尝试复现&#xff0c;但失败了。所幸&#xff0c;我基于此链&#xff0c;发现在这个框架的最新版本中的另一条链。 复现过程 这里使用vscod…...

互联网Java工程师面试题·Java 并发编程篇·第四弹

目录 39、volatile 有什么用&#xff1f;能否用一句话说明下 volatile 的应用场景&#xff1f; 40、为什么代码会重排序&#xff1f; 41、在 java 中 wait 和 sleep 方法的不同&#xff1f; 42、用 Java 实现阻塞队列 43、一个线程运行时发生异常会怎样&#xff1f; 44、…...

3、Linux下安装

以下操作仅限于rh系列:支持rpm/yum安装方式&#xff0c;不支持deb/apt安装方式。 以下操作仅限于rh系列&#xff1a;支持rpm/yum安装方式&#xff0c;不支持 deb/apt安装方式。 1、在线下载安装包&#xff1a; wget https://downloads.mysql.com/archives/get/p/23/file/ m…...

Zookeeper【Curator客户端Java版】从0到1——万字学习笔记

目录 初识Zookeeper Zookeeper作用 维护配置信息 分布式锁服务 集群管理 生产分布式唯一ID Zookeeper的设计目标 Zookeeper 工作机制 数据模型 ZooKeeper 命令操作 服务端常用命令 客户端常用命令 ZooKeeper JavaAPI操作 Curator 介绍 Curator API 常用操作 导入依赖 建立连接 …...

生物标志物发现中的无偏数据分析策略

目录 0. 导论基本概念 1. 生物标志物发现的注意事项2. 数据预处理2.1 高质量原始数据和缺失值处理2.2 数据过滤2.3 数据归一化 3. 数据质量评估3.1 混杂因素3.2 类别分离3.3 功效分析3.4 批次效应 4. 生物标志物发现4.1 策略4.2 数据分析工具4.3 模型优化策略 0. 导论 组学技术…...

华为校招机试题- 机器人活动区域-2023年

题目描述: 现有一个机器人,可放置于 M N的网格中任意位置,每个网格包含一个非负整数编号。当相邻网格的数字编号差值的绝对值小于等于 1 时,机器人可在网格间移动 问题:求机器人可活动的最大范围对应的网格点数目。 说明: 1)网格左上角坐标为 (0, 0),右下角坐标为 (m-…...

半屏小程序

准备工作 tip 管理后台配置 设置-》第三方设置-》半屏小程序管理-》我调用的 添加小程序 有些手机会唤起失败&#xff0c;直接唤起了全屏的小程序&#xff0c;所以我们为了兼容&#xff0c;需要在app.config.ts加上 {"embeddedAppIdList": ["wxxxxxxxx"]/…...

2023年最新Python大数据之Python基础【七】管理系统

文章目录 7、学生管理系统8、函数递归9、lambda函数后记 7、学生管理系统 # 需求拆分:1.展示学生管理系统的功能有哪些,引导用户键入序号选择功能 2.获取用户键入的功能 3.分析具体要执行哪一项功能 4.执行功能 def print_all_option():"""用户功能界面展示&qu…...

【网安】网络安全防止个人信息泄露

网络安全防止个人信息泄露 1、尝试检查自己的网络隐私数据是否泄漏过&#xff0c;可以使用下面的网站2、使用安全非盈利组织的浏览器3、安装浏览器插件&#xff0c;防止网络跟踪4、保持安全的访问方式 1、尝试检查自己的网络隐私数据是否泄漏过&#xff0c;可以使用下面的网站 …...

ChatGPT,AIGC 数据库应用 Mysql 常见优化30例

使用ChatGPT,AIGC总结出Mysql的常见优化30例。 1. 建立合适的索引:在Mysql中,索引是重要的优化手段,可以提高查询效率。确保表的索引充分利用,可以减少查询所需的时间。如:create index idx_name on table_name(column_name); 2. 避免使用select * :尽可能指定要返回的…...

并查集路径压缩

并查集里的 find 函数里可以进行路径压缩&#xff0c;是为了更快速的查找一个点的根节点。对于一个集合树来说&#xff0c;它的根节点下面可以依附着许多的节点&#xff0c;因此&#xff0c;我们可以尝试在 find 的过程中&#xff0c;从底向上&#xff0c;如果此时访问的节点不…...

spring和springMVC的说明

Spring和Spring MVC都是Java应用程序开发中常用的框架&#xff0c;它们提供了一种结构化的方法来构建企业级Java应用程序。下面我将对它们进行详细的说明&#xff1a; Spring&#xff1a; 概述&#xff1a; Spring是一个综合的Java应用程序开发框架&#xff0c;旨在简化企业级…...

软件工程与计算总结(十)软件体系结构设计与构建

目录 ​编辑 一.体系结构设计过程 1.分析关键需求和项目约束 2.选择体系结构风格 3.体系结构逻辑设计 4.体系结构实现 5.完善体系结构设计 6.定义构件接口 二.体系结构原型构建 1.包的创建 2.重要文件的创建 3.定义构件之间的接口 4.关键需求的实现 三.体系结构的…...

【实操】基于ChatGPT构建知识库

前言 最近有些实践&#xff0c;因为后面要去研究fine-tune了&#xff0c;想着记录一下chatgpt向量数据库构建知识库的一些实操经验&#xff0c;不记我很快就忘了&#xff0c;哈哈。 首先&#xff0c;提一下为啥会出现向量数据库这个技术方案&#xff1f; 大家经过实践发现&…...

ribbonx编程笔记-读写注册表与使用自定义对话框

​ Windows 注册表是一个数据库,用于存储与计算机不同方面相关的设置,例如用户设置、应用程序设备、硬件设置,等等。 VBA 提供了与注册表直接交互的方式,这不仅允许我们获取其它程序和硬件的信息,而且也能够使我们选择应用程序中的重要信息并将其存储在注册表中。本文中,…...

网工记背配置命令(3)----POE配置示例

POE 供电就是通过以太网供电&#xff0c;这种方式仅凭借那根连接通信终端的网线就可完成为它们供电。POE提供的是-53V~0v 的直流电&#xff0c;供电距离最长可达 100m。PoE 款型的交换机的软件大包天然支持 POE&#xff0c;无需 license&#xff0c;通过执行 poe-enable 命令使…...

网络安全(黑客技术)—0基础学习手册

目录 一、自学网络安全学习的误区和陷阱 二、学习网络安全的一些前期准备 三、网络安全学习路线 四、学习资料的推荐 想自学网络安全&#xff08;黑客技术&#xff09;首先你得了解什么是网络安全&#xff01;什么是黑客&#xff01; 网络安全可以基于攻击和防御视角来分类…...

[部署网站]01安装宝塔面板搭建WordPress

宝塔面板安装WordPress&#xff08;超详细&#xff09;_Wordpress主题网 参考教程 宝塔面板 - 简单好用的Linux/Windows服务器运维管理面板 官网 1.首先你需要一个服务器或者主机 &#xff08;Windows系统或者Linux系统都可以&#xff09; 推荐Linux系统更稳定&#xff0c;…...

Can We Edit Multimodal Large Language Models?

本文是LLM系列文章&#xff0c;针对《Can We Edit Multimodal Large Language Models?》的翻译。 我们可以编辑多模态大型语言模型吗? 摘要1 引言2 相关工作3 编辑多模态LLM4 实验5 结论 摘要 本文主要研究多模态大语言模型(Multimodal Large Language Models, mllm)的编辑…...