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,一经查实,立即删除!

相关文章

【TB作品】msp430单片机,播放蜂鸣器音乐,天空之城

功能 msp430单片机,连接一个无源蜂鸣器,播放蜂鸣器音乐,天空之城。 适用于所有msp430单片机。 硬件 无源蜂鸣器,接单片机P1.5,使用vcc3.3v供电。 如果根据简谱修改音乐? //第一步 //首先修改music0 的变量&…

城市之旅:使用 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以其…

unity知识点 专项三 Update函数和如何保证物理移动的准确性

一 概念 1.1 unity update 一秒调用多少次 Unity的Update函数在每一帧调用一次,如果您的游戏运行在60帧每秒(这是标准的帧率目标),那么Update函数将在每一秒被调用60次。 这是Unity的默认行为,但实际调用频率可以根…

智驾未来与低代码开发:重塑技术领域的双重革命,引领全新智能时代

在信息化浪潮席卷全球的今天,两大技术趋势——智能驾驶与低代码开发正逐渐崭露头角,它们以其独特的魅力引领着未来科技发展的方向。这两大技术不仅为传统行业注入了新的活力,更催生了众多前所未有的商业模式,使人们的生活变得更加…

计算机组成原理概论 (复习专用)

文章目录 前言一、计算机组成原理概论1.冯诺伊曼体系结构1.基本设计思想2.五大部件1.存储器 2.运算器3.控制器4.5.输入/输出设备 2.计算机语言3.计算机的性能指标1.机器字长2.存储容量3.运算速度4.可靠性、可维护性、可用性5.功耗、能耗 后续看时间,可能会补充例题.…

postman教程-10-使用cookie

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

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

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

*args 与 **kwargs

*args 与 **kwargs *args**kwargs *args 在 Python 中,*args 是一个特殊的语法,用于表示函数定义或调用时的可变参数列表(variable argument list)。这里的星号(*)表示 “任意数量”,而 args 是…

链表任意位置插入删除

链表的插入删除主要是要考虑如果为空表&#xff0c;删除第一个等特殊情况&#xff0c;考虑全面。 具体实现如下 #include<stdlib.h> #include<stdio.h> struct Node {int data;struct Node* next; }; struct Node* head; void print() {struct Node* temp head;p…

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

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

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

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

【2024最新华为OD-C/D卷试题汇总】密码解密 (100分) - 支持在线评测+三语言AC题解(Python/Java/Cpp)

🍭 大家好这里是清隆学长 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢💗 在线评测链接 密码解密(100分) 🌍 评测功能需要订阅专栏后私信联系清隆解锁~…

【Unix】运行时so库动态加载

运行时可以自己自定义so库的动态加载框架&#xff0c;主动去加载某些库&#xff0c;并调用其中的某些方法 首先写一些方法&#xff0c;并生成so库 // hello.cpp#include <iostream>/*使用 nm 命令查看 so 库的内容 */// 1. 使用extern // dlsym(handle, "hello&qu…

Elasticsearch REST API 初探:索引与搜索文档的奥秘

在当今数据驱动的时代&#xff0c;高效的数据检索和存储成为了众多企业和项目的关键需求。Elasticsearch 作为一款基于 Lucene 的开源搜索和分析引擎&#xff0c;凭借其分布式、可扩展和高性能的特性&#xff0c;成为了处理大规模数据的首选工具。本文将带你初步探索 Elasticse…

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

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