JDBC 学习笔记(一)基础篇 - JDBC 搭建的六大步骤

JDK 版本使用:JDK 21

框架思想:实体类及ORM思想

反射技术:BaseDAO 封装的过程

解决现有问题的角度,主要是 JDBC的基础应用

一、、JDBC 可以解决的问题

1.1 数据存储的问题

解决数据长期的存储问题:

  • 数据通过 I/O 流技术,存储在本地磁盘中,解决了持久化问题。但是这个数据没有结构和逻辑,不方便管理和维护。
  • 通过关系型数据库(比如:MySQL),将数据按照特定的格式交由数据库管理系统维护。关系型数据库是通过库和表分隔不同的数据,表中数据存储的方式是行和列,区分相同格式不同值的数据。

1.2 Java 程序读取数据的问题

如何通过 Java 程序对数据库中数据做增删改查?

答:使用JDBC 技术,通过Java 程序来操作数据库。

二、JDBC 概述

2.1 什么是 JDBC

  • JDBC:Java Database Connectivity(Java 数据库连接)
  • JDBC 是 Java 提供的一组独立于任何数据库管理系统的 API
  • Java 提供接口规范,由各个数据库厂商提供接口的实现,厂商提供的实现类封装成 jar 文件(数据库驱动 jar 包
  • 面向接口编程,程序员只关心标准和规范,无需关注实现过程。

2.2 JDBC 的核心组成

JDBC:Java 提供接口,数据库厂商提供实现(数据库驱动),程序员调用实现(数据库驱动)来操作数据库。

1、接口规范

  • 提高了项目代码的可移植性、可维护性。SUN 公司制定了 Java 程序连接各种数据库的统一接口规范。
  • 接口存储在 java.sql 和 javax.sql 包下

2、实现规范

  • 数据库厂商自己实现Java 提供的接口规范
  • 厂商将实现内容和过程封装成 jar 文件,程序员只需要将 jar 文件引入到项目中集成即可,就可以调用实现过程操作数据库了。
  • 驱动从数据库官网上下载

三、JDBC 快速入门

3.1 JDBC 搭建步骤

  1. 准备数据库
  2. 官网下载数据库连接驱动 jar 包:https://downloads.mysql.com/archives/c-j/
  3. 创建 Java 项目,在项目下创建 lib 文件夹,将下载的驱动 jar 包复制到文件夹里。
  4. 选中 lib 文件夹右键 ——》Add as Library,与项目集成
  5. 编写代码

驱动版本:8.0.25 之前的 MySql 驱动是需要设置时区的

3.2 熟悉 JDBC 核心编码六个步骤

package com.atguigu.base;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;public class JDBCQuick {public static void main(String[] args) throws Exception {//        核心六步//1.注册驱动(将厂商提供的驱动类,通过类加载的方式加载到我们程序中来)//Class.forName() 指定要加载的类的全类名Class.forName("com.mysql.cj.jdbc.Driver");//2.获取连接对象String url = "jdbc:mysql://localhost:3306/atguigu";String username = "root";String password = "123456";//拿到连接对象Connection connection = DriverManager.getConnection(url, username, password);//3.获取执行 SQL 语句的对象(把SQL语句发送给MySQL的对象 )Statement statement = connection.createStatement();//4.编写SQL语句,并执行,接收返回的结果集String sql = "select * from t_emp";//返回一个set集合ResultSet resultSet = statement.executeQuery(sql);//5.处理结果:遍历resultSet结果集while (resultSet.next()) {int empId = resultSet.getInt("emp_id");String empName = resultSet.getString("emp_name");double empSalary = resultSet.getDouble("emp_salary");int empAge = resultSet.getInt("emp_age");System.out.println(empId+"\t"+empName+"\t"+empSalary+"\t"+empAge);}//6.释放资源(对象)【先开后关的原则】resultSet.close();statement.close();connection.close();}
}

四、核心 API 

4.1 注册驱动(可省略)

4.2 Connection 接口(⭐)

Connection 代表着一次连接,用完要释放

4.3 Statement 接口

使用 statement 会产生SQL注入的问题:

package com.atguigu.base;import java.sql.*;
import java.util.Scanner;//Injection :注入
public class JDBCInjection {public static void main(String[] args) throws Exception {//1.注册驱动(可以省略)//2.获取连接对象Connection connection = DriverManager.getConnection("jdbc:mysql:///atguigu", "root", "123456");//3.获取执行SQL语句对象Statement statement = connection.createStatement();//动态注入System.out.println("请输入员工姓名:");Scanner scanner = new Scanner(System.in);String name = scanner.nextLine();//4.编写SQL语句,并执行,接收返回的结果集String sql = "select * from t_emp where name = '" + name + "'";ResultSet resultSet = statement.executeQuery(sql);//5.处理结果,遍历resultSetwhile (resultSet.next()) {int empId = resultSet.getInt("emp_id");String empName = resultSet.getString("emp_name");double empSalary = resultSet.getDouble("emp_salary");int empAge = resultSet.getInt("emp_age");System.out.println(empId+"\t"+empName+"\t"+empSalary+"\t"+empAge);}//6.释放资源resultSet.close();statement.close();connection.close();}
}

 

4.4 PreparedStatement 接口(⭐⭐⭐)

package com.atguigu.base;import java.sql.*;
import java.util.Scanner;//prepareStatement
public class JDBCPrepared {public static void main(String[] args) throws Exception {//1.注册驱动(可以省略)//2.获取连接对象Connection connection = DriverManager.getConnection("jdbc:mysql:///atguigu", "root", "123456");//3.获取执行SQL语句对象PreparedStatement preparedStatement = connection.prepareStatement("select * from t_emp where emp_name = ?");//动态注入System.out.println("请输入员工姓名:");Scanner scanner = new Scanner(System.in);String name = scanner.nextLine();//4.为?占位符复制,并执行,接收返回的结果集preparedStatement.setString(1, name);ResultSet resultSet = preparedStatement.executeQuery();//5.处理结果,遍历resultSetwhile (resultSet.next()) {int empId = resultSet.getInt("emp_id");String empName = resultSet.getString("emp_name");double empSalary = resultSet.getDouble("emp_salary");int empAge = resultSet.getInt("emp_age");System.out.println(empId+"\t"+empName+"\t"+empSalary+"\t"+empAge);}//6.释放资源resultSet.close();preparedStatement.close();connection.close();}
}

4.5 ResultSet 接口

只代表查询的结果

ORM:封装

五、基于 PreparedStatement 完成 CRUD,防止SQL 注入

5.1 查询单行单列

/*** 单行单列* @throws Exception*/@Test //引入测试public void testQuerySingleRowAndCol() throws Exception {//1.注册驱动//2.获取连接Connection connection = DriverManager.getConnection("jdbc:mysql:///atguigu", "root", "123456");//3.预编译SQL语句,得到 PreparedStatement 对象PreparedStatement preparedStatement = connection.prepareStatement("select count(*) as count from t_emp");//4.执行SQL语句,获取结果ResultSet resultSet = preparedStatement.executeQuery();//5.处理结果(如果自己明确一定只有一个结果,那么 resultSet 最少要做一次 next的判断,才能拿到我们要的列的结果)while(resultSet.next()) {int count = resultSet.getInt("count");System.out.println(count);}//6.释放资源resultSet.close();preparedStatement.close();connection.close();}

5.2 查询单行多列

/*** 单行多列* @throws Exception*/@Testpublic void testQuerySingleRow() throws Exception {//1.注册驱动Class.forName("com.mysql.cj.jdbc.Driver");//2.获取连接Connection connection = DriverManager.getConnection("jdbc:mysql:///atguigu", "root", "123456");//3.预编译SQL语句获得PreparedStatement对象PreparedStatement preparedStatement = connection.prepareStatement("select * from t_emp where emp_id = ?");//4.为占位符赋值,然后执行,并接收结果preparedStatement.setInt(1,4);ResultSet resultSet = preparedStatement.executeQuery();//5.处理结果while (resultSet.next()) {int empId = resultSet.getInt("emp_id");String empName = resultSet.getString("emp_name");double empSalary = resultSet.getDouble("emp_salary");int empAge = resultSet.getInt("emp_age");System.out.println(empId + "\t" + empName + "\t" + empSalary + "\t" + empAge);}//6.释放资源resultSet.close();preparedStatement.close();connection.close();}

5.3 查询多行多列

/*** 多行多列* @throws Exception*/@Testpublic void testQueryMoreRow() throws Exception {//1.注册驱动Class.forName("com.mysql.cj.jdbc.Driver");//2.获取连接Connection connection = DriverManager.getConnection("jdbc:mysql:///atguigu", "root", "123456");//3.预编译SQL语句,获取PreparedStatement对象PreparedStatement preparedStatement = connection.prepareStatement("select * from t_emp where emp_age > ?");//4.为占位符赋值,然后执行,并获取结果preparedStatement.setInt(1,25);ResultSet resultSet = preparedStatement.executeQuery();//5.处理结果while(resultSet.next()){int empId = resultSet.getInt("emp_id");String empName = resultSet.getString("emp_name");double empSalary = resultSet.getDouble("emp_salary");int empAge = resultSet.getInt("emp_age");System.out.println(empId + "\t" + empName + "\t" + empSalary + "\t" + empAge);}//6.释放资源resultSet.close();preparedStatement.close();connection.close();}

5.4 新增

/*** 新增* @throws Exception*/@Testpublic void testInsert() throws Exception {//1.注册驱动Class.forName("com.mysql.cj.jdbc.Driver");//2.获取连接Connection connection = DriverManager.getConnection("jdbc:mysql:///atguigu", "root", "123456");//3.预编译SQL语句,获取PreparedStatement对象PreparedStatement preparedStatement = connection.prepareStatement("insert into t_emp(emp_name,emp_salary,emp_age) values (?,?,?)");//4.为占位符赋值,然后执行,并获取结果preparedStatement.setString(1,"rose");preparedStatement.setDouble(2,345.67);preparedStatement.setInt(3,28);int result = preparedStatement.executeUpdate();//5.处理结果if(result > 0){System.out.println("成功!");} else {System.out.println("失败!");}//6.释放资源preparedStatement.close();connection.close();}

5.5 修改

/*** 修改* @throws Exception*/@Testpublic void testUpdate() throws Exception {//1.注册驱动Class.forName("com.mysql.cj.jdbc.Driver");//2.获取连接Connection connection = DriverManager.getConnection("jdbc:mysql:///atguigu","root","123456");//3.预编译SQL语句,获取PreparedStatement对象PreparedStatement preparedStatement = connection.prepareStatement("update t_emp set emp_salary = ? where emp_id = ?");//4.为占位符赋值,然后执行,并获取结果preparedStatement.setDouble(1,888.88);preparedStatement.setInt(2,6);//5.处理结果int result = preparedStatement.executeUpdate();if(result > 0){System.out.println("成功!");}else {System.out.println("失败!");}//6.释放资源preparedStatement.close();connection.close();}

5.6 删除

/*** 删除* @throws Exception*/@Testpublic void testDelete() throws Exception {//1.加载驱动Class.forName("com.mysql.cj.jdbc.Driver");//2.获取连接Connection connection = DriverManager.getConnection("jdbc:mysql:///atguigu", "root", "123456");//3.预编译SQL语句,获取PreparedStatement对象PreparedStatement preparedStatement = connection.prepareStatement("delete from t_emp where emp_id = ?");//4.为占位符赋值,然后执行,并获取结果preparedStatement.setInt(1,6);int result = preparedStatement.executeUpdate();//5.处理结果if (result>0){System.out.println("成功!");}else {System.out.println("失败!");}//6.释放资源preparedStatement.close();connection.close();}

六、常见问题

6.1 资源的管理

在使用 JDBC 的相关资源时,比如 Connection、PreparedStatement、ResultSet,使用完毕后,要及时关闭这些资源以释放数据库服务器资源和避免内存泄漏是很重要的。

6.2 SQL 语句问题:SQLSyntaxErrorException

6.3 SQL 语句未设置参数问题

6.4 用户名或密码错误问题

6.5 通信异常:CommunicationsException

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

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

相关文章

城市之旅:使用 LLM 和 Elasticsearch 简化地理空间搜索(一)

作者:来自 Elastic Philipp Kahr, Valentin Crettaz 这篇博文的本地部署实践 Jupyter notebook 请详细阅读文章 “城市之旅:使用 LLM 和 Elasticsearch 简化地理空间搜索(二)”。 探索如何从自然语言提问创建地理空间搜索。在下…

最新鸿蒙南北开发学习路线+学习资料分享

前言 5月29日,“千帆竞发启航 共筑鸿蒙生态”鸿蒙原生应用合作仪式在北京成功举办,近40个应用现场官宣启动鸿蒙原生应用开发。此次官宣启动开发的鸿蒙原生应用不仅包括教育、母婴、出行、医疗健康等多领域的知名应用,还有十多家企业内部办公应…

OverlayFS在嵌入式系统中的应用

文章目录 抛出问题基本概念使用场景OverlayFS的详细介绍框架目录合并修改文件删除文件添加文件小结 OverlayFS在嵌入式系统中的应用内核配置OverlayFS简单应用OverlayFS应用新思路 总结 环境介绍 硬件:T113平台 软件:Tina5.0 SDK(使用的build…

【第3章】SpringBoot实战篇之登录接口(含JWT和拦截器)

文章目录 前言一、JWT1. 什么是JWT2. 使用场景3. 结构3.1 Header3.2 Payload3.3 Signature 4. 使用 二、案例1.引入库2.JwtUtils3. UserController14. ArticleController 三、拦截器1. 定义拦截器2. 注册拦截器 四、测试1. 登录2. 无token3. 有token4. 全局配置 总结 前言 前面…

485通讯网关

在工业自动化与智能化的浪潮中,数据的传输与交互显得尤为重要。作为这一领域的核心设备,485通讯网关凭借其卓越的性能和广泛的应用场景,成为了连接不同设备、不同协议之间数据转换和传输的桥梁。在众多485通讯网关中,HiWoo Box以其…

postman教程-10-使用cookie

领取资料,咨询答疑,请➕wei: June__Go 上一小节我们学习了Postman Authorization授权的几种方法,本小节我们讲解一下Postman 使用cookie的方法。 Postman 的 cookie 管理器使您能够查看和编辑与不同域关联的 cookie。您可以为域手动创建 c…

软件测试、测试模型、测试用例

软件开发的五个模型 瀑布模型(Waterfall Model) 瀑布模型是所有其他模型的基础框架,瀑布模型的每个阶段都只执行一次,因此是线性顺序进行的开发模式优点:强调开发的阶段性; 强调早期计划及需求调查&#…

【Python实战】使用postman测试flask api接口

cookie_demo.py # -*- coding: utf-8 -*- """ Time : 2024/5/28 17:14 Author : 娜年花开 File : cookie_demo.py Desc : 需求:用户需要先登陆,登陆之后,通过Cookie来判断是不是能够访问登录后的接口userinfo &quo…

TMS FNC WX Pack TMS软件分发的一组应用程序

TMS FNC WX Pack TMS软件分发的一组应用程序 TMS FNC WX Pack是由TMS软件分发的一组应用程序。这些活动是100%的跨平台和跨Frimorc,并在不同的应用程序中得到支持,如Web应用程序、Windows、Linux等。阿拉伯语视觉组件库。安装这些计算机的过程非常简单高…

第四讲 单片机STC89C52+RA8889代码移植范例(包含API接口)

本次介绍单片机STC89C52RA8889代码移植范例,该范例已将RA8889的API移植好了,下方提供下载地址。 硬件平台:89C52RA8889 采用SPI通信方式 (已测试通过) 上一讲已经阐述RA8889移植到51单片机的基本方法,本讲增加了API…

【第一节】数据结构和算法绪论

目录 一、数据结构的起源与发展 二、什么是数据结构 三、数据的逻辑结构和存储结构 四、数据类型和数据结构 五、算法 六、算法与数据结构的关系 七、算法时间复杂度和空间复杂度 一、数据结构的起源与发展 数据结构的起源可以追溯至1968年。当时,美国的唐欧…

Spring Security 注册过滤器注意事项

前两天和小伙伴聊了 Spring SecurityJWT 实现无状态登录,然后有小伙伴反馈了一个问题,感觉这是一个我们平时写代码容易忽略的问题,写一篇文章和小伙伴们聊一聊。 一 问题复原 先来说问题吧,在 Spring SecurityJWT 登录中&#x…

C++入门5——C/C++动态内存管理(new与delete)

目录 1. 一图搞懂C/C的内存分布 2. 存在动态内存分配的原因 3. C语言中的动态内存管理方式 4. C内存管理方式 4.1 new/delete操作内置类型 4.2 new/delete操作自定义类型 1. 一图搞懂C/C的内存分布 说明: 1. 栈区(stack):在…

【C语言】位段(结构体实现位段)

目录 一、位段的定义 二、位段的声明 三、位段的内存分配 四、位段在内存中的存储方式 五、位段的优点 六、位段的跨平台问题 七、位段的应用 八、位段使用的注意事项 一、位段的定义 信息的存取一般以字节为单位。实际上,有时存储一个信息不必用一个或多个字…

匠心独运,B 端系统 UI 演绎华章之美

匠心独运,B 端系统 UI 演绎华章之美

上位机图像处理和嵌入式模块部署(f103 mcu获取唯一id)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 对于stm32f103系列mcu来说,一般每一颗原厂的mcu,都会对应一个唯一的id。那这个id可以用来做什么用呢?个人认为&…

PX4 ROS2 真机

如果仿真跑通了。 真机遇到问题,可参考此文章。 ubuntu22 px4 1.14.3 ros2 humble 硬件接线。 先找两个usb - ttl串口,分别接到两台主机上,保证串口通信正常。 图中是个六合一的。浪费一天时间,发现是串口设置错误&#xff…

力扣 101. 对称二叉树

给你一个二叉树的根节点 root , 检查它是否轴对称。 /*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/ bool check(struct TreeNode* L,struct TreeNode* R){if(!L&…

socket网络编程——套接字地址结构

一、通用 socket 地址结构 socket 网络编程接口中表示 socket 地址的是结构体 sockaddr&#xff0c;其定义如下&#xff1a; 1. #include <bits/socket.h> 2. 3. struct sockaddr 4. { 5. sa_family_t sa_family; 6. char sa_data[14]; 7. }; sa_family 成员是地址族类型…

【云原生】kubernetes中pod的生命周期、探测钩子的实战应用案例解析

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…