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.处理结果,遍历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();
    }
}

 

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.处理结果,遍历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();
    }
}

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
     */
    @Test
    public 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
     */
    @Test
    public 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
     */
    @Test
    public 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
     */
    @Test
    public 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
     */
    @Test
    public 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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

24.Labview移位寄存器的使用及数据流解析

本文讲解移位寄存器的常用场景及其数据流的方向解析。 在Labview中移位寄存器是存在于循环结构中的,也就是说for循环和while循环中,在了解移位寄存器之前首先要了解一下for循环和while循环的原理及其数据流的流动方向,题主之前讲过for循环的文…

使用python绘制华夫饼图

使用python绘制华夫饼图 华夫饼图效果代码 华夫饼图 华夫饼图(Waffle Chart)是一种数据可视化图表,用于显示数据在一个网格中的分布情况。它类似于饼图,通过将数据划分为等大小的方块来表示不同类别的比例。华夫饼图的优势在于它…

国联易安:网络反不正当竞争,要防患于未然

据市场监管总局官网消息,为预防和制止网络不正当竞争,维护公平竞争的市场秩序,鼓励创新,保护经营者和消费者的合法权益,促进数字经济规范健康持续发展,市场监管总局近日发布《网络反不正当竞争暂行规定》&a…

I2C通信协议

I2C通信协议 项目要求是,通过通信线,是实现单片机读写外挂模块寄存器的功能,至少实现,在指定位置写寄存器和在指定位置读寄存器,实现了读写寄存器,就实现对模块的控制。 MPU6050,OLED&#xf…

第六篇 移位寄存器

实验六 移位寄存器 6.1实验目的 掌握移位寄存器的工作原理; 掌握利用移位寄存器实现串行与并行的相互转换; 掌握使用移位寄存器实现乘除法运算; 6.2 原理介绍 6.2.1 基本移位寄存器 在实验四中,我们主要介绍了寄存器的结构…

QGIS 根据点图层上的点 画线生成线图层

使用节点捕捉功能 空白处鼠标右键---》勾选捕捉工具栏----》选中磁铁工具 创建线图层---》编辑模式---》点击新增线工具--》鼠标靠近点,会有高亮提醒,左键选中,右键结束当前线段绘制

千帆 AppBuilder 工作流编排功能直播总结

千帆 AppBuilder 工作流编排功能直播总结 ​ 上个月,千帆AppBuilder推出了一项引人瞩目的新功能——工作流编排。在官方直播中,百度产品经理不仅深入介绍了这项功能,而且还通过创建多个组件,生动展示了AppBuilder组件工作流的强大…

网络工程师---第四十六天

1、逻辑网络结构设计阶段中,要想实现核心层与汇聚层交换机全部互相连接,组网技术有哪些? 2、工作区子系统的通信布线规范有哪些? 3、综合布线中施工规范有哪些? 4、综合布线系统中核心机房通常包括哪些设备&#xff1f…

API商品数据接口(电商数据api)返回京东淘宝商品详情数据提高开发效率

众多品牌选择使用比价工具进行采购,主要是出于以下几个重要原因: 提高开发效率:电商数据采集API接口允许不同的应用程序之间高效地进行交互,节省了大量的人力物力成本,使得开发者可以将更多时间和精力集中于自身的核心…

分库分表方案

文章目录 分库分表设计思路hash取模和范围方案最终方案采用hash取模和rang范围两者相结合 分库分表设计思路 首先分库分表有两种方式,一种是垂直拆分,一种是水平拆分。 垂直拆分 垂直拆分比较简单,也就是本来一个数据库,数据量大…

小红书前端2轮面试期望22K,全程问低代码设计

一面(通过) 1、好,那我们开始把,先简单介绍一下自己的一个经历,以及自己有亮点的项目?balabala 2、你可以这样介绍:在这里边主要负责哪几个项目,哪些项目是比较有亮点的&#xff0…

超市管理系统设计1——基本功能设计

超市管理系统基础功能类设计 1. 概述 本设计文稿提供一个基础的超市管理系统,包含基本的功能设计。该系统将管理商品、顾客、员工和交易记录,不需要接入数据库,通过文件存储数据,并满足面向对象编程的基本要求(继承、…

LabVIEW开发EOL功能测试系统

LabVIEW开发EOL功能测试系统 介绍了一种基于LabVIEW开发的EOL功能测试系统方案,涵盖软件架构、工作流程、模块化设计、低耦合性、易于修改与维护、稳定性及硬件选型。系统通过高效的CAN通信实现对电机控制器的全面测试,确保运行可靠并支持未来的升级需求…

媒体有入口,发稿有入口 是什么意思?

传媒如春雨,润物细无声,大家好,我是51媒体网胡老师。 媒体有入口,发稿有入口是指在新闻媒体发稿时,稿件可以通过一定的路径被访问和浏览。具体来说,有入口的新闻稿件可以通过点击链接,逐步深入…

PyTorch深度学习实战(44)——基于 DETR 实现目标检测

PyTorch深度学习实战(44)——基于 DETR 实现目标检测 0. 前言1. Transformer1.1 Transformer 基础1.2 Transformer 架构 2. DETR2.1 DETR 架构2.2 实现 DETR 模型 3. 基于 DETR 实现目标检测3.1 数据加载与模型构建3.2 模型训练与测试 小结系列链接 0. 前…

第 10 章 动态参数(自学二刷笔记)

重要参考: 课程链接:https://www.bilibili.com/video/BV1Ci4y1L7ZZ 讲义链接:Introduction Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程 10.2动态参数 参数服务器的数据被修改时,如果节点不重新访问,那么就不能获取修改后的…

MySQL的组成与三种log

MySQL由几块组成 连接器分析器优化器执行器 MySQL的三大log blog 作用&#xff1a; 用于主从同步与数据恢复 记录内容&#xff1a; 已经完成的 DML(数据操作语句)&#xff0c;主要是用于数据备份 redolog<重试日志> 作用&#xff1a; 崩溃恢复&#xff0c;用于事…

Linux - 高级IO

目录 理解五种IO模型非阻塞IO的设置多路转接之select 实现一个简易的select服务器select服务器的优缺点 多路转接之poll 实现一个简易的poll服务器poll服务器的优缺点 多路转接之epoll epoll原理epoll的优势用epoll实现一个简易的echo服务器 epoll的LT和ET工作模式 什么是LT和…

【mysql】数据报错: incorrect datetime value ‘0000-00-00 00:00:00‘ for column

一、问题原因 时间字段在导入值0000-00-00 00:00:00或者添加 NOT NULL的时间字段时&#xff0c;会往mysql添加0值&#xff0c;此时可能出现此报错。 这是因为当前的MySQL不支持datetime为0&#xff0c;在MySQL5.7版本以上&#xff0c;默认设置sql_mode模式包含NO_ZERO_DATE, N…

实验名称:组合数据类型

大家好&#xff01;欢迎收听你的月亮我的心&#xff01;我是肖老师&#xff01;好久不见&#xff01; 目录 一、实验目的&#xff1a; 二、实验环境&#xff1a; 三、实验步骤&#xff1a; 四、实验结果&#xff1a; 1.已知列表li_one[1,2,1,2,3,5,4,3,5,7,4,7,8],删除列…