软件设计之JDBC(1)

news2025/2/23 22:50:28

软件设计之JDBC(1)

此篇应在MySQL之后进行学习:
路线图推荐:
【Java学习路线-极速版】【Java架构师技术图谱】
尚硅谷2024最新JDBC教程 | jdbc基础到高级一套通关!

资料可以去尚硅谷官网免费领取

学习内容:

  1. 前言
  2. JDBC
  3. PreparedStatement实现CRUD
  4. 常见问题

1、前言

1、开发Java程序时,数据都是存储在内存中,属于临时存储,当程序停止或重启时,内存中的数据就丢失了
2、因此数据通过I/O技术,存储在本地磁盘中,解决了持久化问题,但是没有结构和逻辑,不方便管理和维护
3、通过关系型数据库,将数据可以按照特定的格式交由数据库管理系统维护。关系型数据库是通过库和表分隔不同的数据,表中数据存储的方式是行和列,区分相同格式不同值的数据。
4、如何通过Java程序对数据库中的数据做增删改查?JDBC

2、JDBC

JDBC概念

JDBC:Java Database Connectivity
JDBC是Java提供的一组独立于任何数据库管理系统的API
Java提供接口规范,后由数据库厂商提供接口的实现
在这里插入图片描述

项目入门

使用select version() from DUAL;语句在Navicat中查看MySQL版本
下载MySQL对应JDBC驱动,下载官网点击此处
找到对应MySQL版本,其中Operating System这里选择Platform independent
下载好的驱动导入到项目里并右键Add as library(具体看视频教程哦)
其中JDK使用的是JDK21

数据库SQL语句创建表

CREATE DATABASE atguigu;
USE atguigu;
CREATE TABLE t_emp
(
  emp_id INT AUTO_INCREMENT COMMENT '员工编号' PRIMARY KEY,
  emp_name VARCHAR(100) NOT NULL COMMENT '员工姓名',
  emp_salary DOUBLE(10,5) NOT NULL COMMENT '员工薪资',
  emp_age INT NOT NULL COMMENT '员工年龄'
);
INSERT INTO t_emp(emp_name,emp_salary,emp_age)
VALUES ('andy',777.77,32),
('大风哥',666.66,41),
('康师傅',111,23),
('Gavin',123,26),
('小鱼儿',123,28);

Java对应语句

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("com.mysql.cj.jdbc.Driver");
        //2 获取连接对象
        String url = "jdbc:mysql://localhost:3306/atguigu";
        String username = "root";
        String password = "root";
        Connection connection = DriverManager.getConnection(url, username, password);
        //3 获取执行SQL语句对象
        Statement statement = connection.createStatement();
        //4 编写SQL语句,并执行,接收返回的结果集
        String sql = "SELECT emp_id,emp_name,emp_salary,emp_age FROM t_emp";
        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();
    }
}

注册驱动

在这里插入图片描述

Connection

在这里插入图片描述

Statement

在这里插入图片描述

SQL注入攻击问题

当控制台输入 a’ or ‘1’ = ‘1 时候,会把所有数据显示
‘a’ or ‘1’ = ‘1’
因为 在SQL语句中WHERE emp_name = true 时,所有都为真

public class JDBCInjection{
    public static void main(String[] args) throws SQLException {
        //1 注册驱动 可省略
        //2 获取连接对象
        String url = "jdbc:mysql://localhost:3306/atguigu";
        String username = "root";
        String password = "root";
        Connection connection = DriverManager.getConnection(url, username, password);
        //3 获取执行SQL语句对象
        Statement statement = connection.createStatement();
        System.out.println("请输入员工姓名:");
        Scanner scanner = new Scanner(System.in);
        String name = scanner.nextLine();
        //4 编写SQL语句,并执行,接收返回的结果集
        String sql = "SELECT emp_id,emp_name,emp_salary,emp_age FROM t_emp WHERE emp_name = '"+name+"'";
        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();
    }
}

PreparedStatement

在这里插入图片描述

package com.atguigu.base;
import java.sql.*;
import java.util.Scanner;
public class JDBCPrepared {
    public static void main(String[] args) throws SQLException {
        //1 注册驱动 可省略
        //2 获取连接对象
        String url = "jdbc:mysql://localhost:3306/atguigu";
        String username = "root";
        String password = "root";
        Connection connection = DriverManager.getConnection(url, username, password);
        //3 获取执行SQL语句对象
        PreparedStatement preparedStatement = connection.prepareStatement("SELECT emp_id,emp_name,emp_salary,emp_age FROM t_emp WHERE emp_name = ?");
        System.out.println("请输入员工姓名:");
        Scanner scanner = new Scanner(System.in);
        String name = scanner.nextLine();
        //4 为?占位符赋值,并执行SQL语句,接收返回的结果集
        //下标从1开始,此处参数只有一个emp_name
        preparedStatement.setString(1,name);
        ResultSet resultSet = preparedStatement.executeQuery();
        //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();
        preparedStatement.close();
        connection.close();
    }
}

ResultSet

在这里插入图片描述

3、PreparedStatement实现CRUD

前期准备

需要下载junit-4.12.jar 和hamcrest-2.2.jar包导入进项目中
下载地址可以点击此处:
下载链接1对应junit
下载链接2对应hamcrest

单行单列查询

    @Test
    public void testQuerySingleRowAndCol() throws SQLException {
        //1 注册驱动 可省略
        //2 获取连接对象
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/atguigu", "root", "root");
        //3 获取执行SQL语句对象
        PreparedStatement preparedStatement = connection.prepareStatement("SELECT COUNT(*) as count FROM t_emp");
        //4 执行SQL语句,接收返回的结果集
        ResultSet resultSet = preparedStatement.executeQuery();
        //5 处理结果:遍历resultSet结果集
        while(resultSet.next()){
            int count = resultSet.getInt("count");
            System.out.println(count);
        }
        //6 释放资源 先开后关原则
        resultSet.close();
        preparedStatement.close();
        connection.close();
    }

单行多列查询

@Test
    public void testQuerySingleRow() throws SQLException {
        //1 注册驱动 可省略
        //2 获取连接对象
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/atguigu", "root", "root");
        //3 获取执行SQL语句对象
        PreparedStatement preparedStatement = connection.prepareStatement("SELECT emp_id,emp_name,emp_salary,emp_age FROM t_emp WHERE emp_id = ?");
        //4 为?占位符赋值,并执行SQL语句,接收返回的结果集
        preparedStatement.setInt(1,3);
        ResultSet resultSet = preparedStatement.executeQuery();
        //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();
        preparedStatement.close();
        connection.close();
    }

多行多列查询

    @Test
    public void testQueryMoreRow() throws SQLException {
        //1 注册驱动 可省略
        //2 获取连接对象
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/atguigu", "root", "root");
        //3 获取执行SQL语句对象
        PreparedStatement preparedStatement = connection.prepareStatement("SELECT emp_id,emp_name,emp_salary,emp_age FROM t_emp WHERE emp_age > ?");
        //4 为?占位符赋值,并执行SQL语句,接收返回的结果集
        preparedStatement.setInt(1,25);
        ResultSet resultSet = preparedStatement.executeQuery();
        //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();
        preparedStatement.close();
        connection.close();
    }

新增一条数据

 @Test
    public void testInsert() throws SQLException {
        //1 注册驱动 可省略
        //2 获取连接对象
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/atguigu", "root", "root");
        //3 获取执行SQL语句对象
        PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO t_emp(emp_name,emp_salary,emp_age) VALUES (?,?,?)");
        //4 为?占位符赋值,并执行SQL语句,接收返回的结果集
        preparedStatement.setString(1,"Rose");
        preparedStatement.setDouble(2,888.88);
        preparedStatement.setInt(3,28);
        int result = preparedStatement.executeUpdate();
        //5 处理结果:根据受影响的行数做判断,得到成功或失败
        if (result > 0){
            System.out.println("成功");
        }else {
            System.out.println("失败");
        }
        //6 释放资源 先开后关原则
        preparedStatement.close();
        connection.close();
    }

修改一条数据

    @Test
    public void testUpdate() throws SQLException {
        //1 注册驱动 可省略
        //2 获取连接对象
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/atguigu", "root", "root");
        //3 获取执行SQL语句对象
        PreparedStatement preparedStatement = connection.prepareStatement("UPDATE t_emp SET emp_salary = ? WHERE emp_id = ?");
        //4 为?占位符赋值,并执行SQL语句,接收返回的结果集
        preparedStatement.setDouble(1,999.99);
        preparedStatement.setInt(2,6);
        int result = preparedStatement.executeUpdate();
        //5 处理结果:根据受影响的行数做判断,得到成功或失败
        if (result > 0){
            System.out.println("成功");
        }else {
            System.out.println("失败");
        }
        //6 释放资源 先开后关原则
        preparedStatement.close();
        connection.close();
    }

4、常见问题

java.sql.SQLSyntaxErrorException

1、SQL语句有错误,建议SQL语句在SQL工具中测试后再复制到java程序中
2、连接数据库的URL中,数据库名称编写错误

java.sql.SQLException:No value specified parameter 1

在使用预编译SQL时,如果有?占位符,要为每一个占位符赋值,否则报该错误

java.sql.SQLException: Access denied for user ‘root’@‘localhost’(using password: YES)

连接数据库时,如果用户名或密码输入错误,也会报SQLException

CommunicationException:Communication link failure

在连接数据库的URL时,如果IP或端口写错了,会报如下异常

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

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

相关文章

IAR查看程序占用的内存空间

参考:IAR分析内存重要的神器 - map文件全解析-CSDN博客 IAR软件*.map文件查看程序占用ROM和RAM大小_iar 通过map文件查看占用内存空间-CSDN博客 编译工程后,可以在MAP文件的最后面查看,程序占用空间的大小 readonly code和readonly data使用…

OPenCV结构分析与形状描述符(1)近似多边形轮廓顶点的函数approxPolyDP()的使用

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 按指定的精度近似一个多边形曲线 cv::approxPolyDP 函数使用另一条曲线或多边形来近似一条曲线或多边形,新曲线或多边形的顶点数较少…

PYTHON发送邮件详细流程

不求别的你要是觉得有用给我一个关注攒攒❤ 安装第三方库 dos命令窗口 pip install pyEmail 两个邮箱准备齐: 我让我的163邮箱做服务器向qq邮箱发邮件 互联网上的两个软件要想通信要有协议,因此开启协议 import smtplib #协议包 from email.mime.t…

【路径规划】2D/3D RRT* 算法 - 使用快速探索随机树进行最优路径规划

摘要 本文介绍了快速探索随机树星(RRT* )算法在2D和3D空间中的实现,用于最优路径规划。RRT*算法通过增量采样的方法,不断优化路径,以收敛到全局最优解。2D版本结合避障功能,能够有效避开给定的障碍物&…

IP地址与物理地址:‌区别解析及在网络通信中的作用

在网络通信的广阔领域中,‌IP地址与物理地址是两个至关重要的概念。‌尽管它们在网络连接和数据传输中都扮演着举足轻重的角色,‌但二者之间存在着本质的区别。‌下面一起跟着虎观代理小二了解IP地址与物理地址的区别,‌并解析它们在网络通信…

ActiViz实战:使用Actor2D画一个二维网格

文章目录 一、效果预览二、交互三、C#源码示例一、效果预览 二、交互 1、能实现等比缩放 2、不允许平移和旋转 3、能够与三维坐标大小匹配 三、C#源码示例 private void AddCudeAxes2D() {double scale =

SprinBoot+Vue餐厅点餐系统的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 application.yml3.5 SpringbootApplication3.5 Vue 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍:CSDN认证博客专家,CSDN平台Java领域优质…

【自动驾驶】控制算法(七)离散规划轨迹的误差计算

写在前面: 🌟 欢迎光临 清流君 的博客小天地,这里是我分享技术与心得的温馨角落。📝 个人主页:清流君_CSDN博客,期待与您一同探索 移动机器人 领域的无限可能。 🔍 本文系 清流君 原创之作&…

SOMEIP_ETS_086: Eventgroup_EventsAndFieldsAll_2_TCP

测试目的: 验证设备(DUT)是否能够针对事件组0x02发送SubscribeEventgroupAck,并且发送所有初始字段。 描述 本测试用例旨在检查DUT在接收到针对事件组0x02的SubscribeEventgroup消息后,是否能够正确响应SubscribeEv…

覆盖 7 百万问答数据,上海 AI Lab 发布 ChemLLM,专业能力比肩 GPT-4

随着人工智能技术的飞速发展,大语言模型 (LLMs) 凭借其强大的自然语言处理能力,在生命科学、海洋学、材料化学等科学研究中被广泛应用。虽然,LLMs 在分子特性预测、分子生成和实验方案设计等化学相关任务上表现良好,但在处理各种化…

IDEA莫名奇妙自动选择光标所在行 -罪魁祸首居然是钉钉

请看受害者视角 作为开发者,工作时基本都会运行钉钉吧。最近,钉钉更新了AI功能,但不知道是不是开发团队平时不使用IDE,竟然让这个AI功能影响到了其他软件,简直让人无语。不仅仅是IDEA受影响,就连WebStorm也…

<C++> AVLTree

目录 1. AVL概念 2. AVL树节点的定义 3. AVL树的插入 4. AVL树的旋转 5. AVL树的验证 6. AVL树的删除 7. AVL树的性能 暴力搜索、二分搜索、二叉搜索树、二叉平衡搜索树(AVL、红黑树)、多叉平衡搜索树(B树)、哈希表 1. AVL概念 二…

RAG 实践- Ollama+RagFlow 部署本地知识库

前言 本文我们介绍另一种实现方式:利用 OllamaRagFlow 来实现,其中 Ollama 中使用的模型仍然是Qwen2 我们再来回顾一下 RAG 常见的应用架构 RagFlow的安装和部署 前置条件 CPU > 4 核RAM > 16 GBDisk > 50 GBDocker > 24.0.0 & Dock…

迅为RK3568 开发板赋能数字广告,推动智能化使用北京迅为RK3568核心板作为广告机主控

广告机作为一种高效且灵活的宣传工具,正逐步成为商场、车站、机场等各类公共场所的标配。广告机通过数字化的方式展示广告内容和提供实时信息更新,有效地提升了广告和信息的覆盖率。 如何设计一款广告机,根据广告机的需求和工作环境&#x…

2024年住宅代理市场概况:趋势与选择指南

在数字化时代,网络安全和数据保护越来越受到重视。尤其在网络环境中,真实的IP地址成为保护个人信息安全和数据安全的重要抓手。住宅代理作为一种有效的解决方案,在这个领域扮演了关键角色。本文将探讨2024年住宅代理市场的概况,分…

【CTF Web】BUUCTF Upload-Labs-Linux Pass-03 Writeup(文件上传+PHP+特殊可解析扩展名绕过)

Upload-Labs-Linux 1 点击部署靶机。 简介 upload-labs是一个使用php语言编写的,专门收集渗透测试和CTF中遇到的各种上传漏洞的靶场。旨在帮助大家对上传漏洞有一个全面的了解。目前一共20关,每一关都包含着不同上传方式。 注意 1.每一关没有固定的…

数据库:笔记01绪论

基本概念 数据(Data) 描述事物的符号记录称为数据,并且可以数字化存入计算机。 数据的含义称为数据的语义,数据与其语义是不可分的。 数据库(DataBase,DB) 存放数据的仓库 数据库数据具有永久存储、有…

【大模型测评】2024大语言模型综合能力测评报告(免费下载)

前言 2024年大语言模型综合能力测评报告揭示了全球大模型市场的爆发式增长,特别是在算法架构、数据处理和应用场景上的显著进步。 从2017年的诞生阶段到2023年的爆发期,大模型技术经历了从Transformer神经网络架构的奠基到多模态理解与内容生成能力的飞…

笔试,牛客.kotori和n皇后​,牛客.AOE还是单体

目录 牛客.kotori和n皇后​编辑 牛客.AOE还是单体 牛客.kotori和n皇后 想起来,我之前还写过n皇后的题,但是这个我开始只能想到暴力解法 判断是不是斜对角线,联想yxb和y-xb,假如在一条线上,那么他们的x和y会对应成比例&#xff0c…

iscntrl函数讲解 <ctype.h>头文件函数

目录 1.头文件 2.iscntrl函数 1.头文件 以上这些函数都属于头文件<ctype.h>中的函数,其中包括iscntrl函数 #include<ctype.h> 2.iscntrl函数 简述&#xff1a;iscntrl 函数用来判断字符是否为控制字符&#xff0c;控制字符为ASCII值在0x00到0x7f之间 控制字符主…