java程序员入行科目一之CRUD轻松入门教程(一)
之前在操作MySQL的时候,都是采用Navicat,或者cmd黑窗口。
无论使用什么方式和MySQL交互,大致步骤是这样的
- 建立连接,需要输入用户名和密码
- 编写SQL语句,和数据库进行交互
这个连接方式不会变,但是现在需要 基于Java语言去和MySQL进行一波

在实际开发中,当用户要对数据进行一些改变的时候,不能通过工具去执行SQL或者直接点来点去修改的,需要用Java语言去进行交互,使用Java会让操作更有效率和准确性。
Java语言为了提供和多种数据库都可以用一样的方式进行交互,Java提供了一个规范,这个规范 JDBC(Java Database Connectivity)
JDBC介绍
什么是JDBC
JDBC就是Java对外提供的一种规范,JDBC的目的就是让Java语言可以和数据库进行交互,完成CRUD。
JDBC的核心思想
JDBC是个规范,Java就对外发布了这个规范,如果各个数据库厂商,想让你的数据库可以和Java进行交互,数据库厂商就需要根据我JDBC的规范去做具体的实现,提供一个驱动(Driver)。

MySQL数据库驱动
这里在课程资料中会提供,如果想自行下载,可以去一个地址搜索。
http://mvnrepository.com
可以直接搜索需要的jar包,只要大版本没问题,正常下载即可

JDBC API
JDBC的API主要掌握4个,了解1个。
| 类型 | 类的全路径 | 描述 |
|---|---|---|
| class | java.sql.DriverManager | 管理数据库的驱动类,需要基于他来获取到Connection连接对象 |
| interface | java.sql.Connection | 代表一个和数据库的连接,通过他获取到Statement发送SQL |
| interface | java.sql.Statement | 将SQL语句发送给数据库服务端 |
| interface | java.sql.ResultSet | 数据库服务端执行完毕SQL后的返回结果 |
| class | java.sql.SQLException | 和数据库交互时,会抛出的异常。 |
JDBC开发步骤
构建项目

导入依赖
第一步,先将jar文件copy到项目的所在目录下。

第二步,需要将这个jar包添加到工程中。

第三步,随便搞一个测试类,看一下Driver类有没有MySQL提供的驱动

编写开发过程
注册驱动
// ### 注册驱动
// 本质就是将Driver类构建好对象并且封装好,将封装好的Driver对象扔到DriverManager类中的一个List集合中
Class.forName("com.mysql.cj.jdbc.Driver");
建立连接
// ### 建立连接
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?characterEncoding=utf-8",
"root","root");
获取发送SQL的对象
// ### 获取发送SQL的对象
Statement statement = conn.createStatement();
执行SQL
// ### 执行SQL
String sql = "insert into account (id,name,money) values (5,'赵六',9999)";
int count = statement.executeUpdate(sql);
处理结果
// ### 处理结果
if(count == 1){System.out.println("当前操作成功!");
}
释放资源
// 释放资源
statement.close();
conn.close();
完整操作
package com.jimihua;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;/*** 在当前类中完成最基本的和MySQL交互。* 完成一个添加操作。*/
public class Demo1 {public static void main(String[] args) throws ClassNotFoundException, SQLException {
// ### 注册驱动
// 本质就是将Driver类构建好对象并且封装好,将封装好的Driver对象扔到DriverManager类中的一个List集合中Class.forName("com.mysql.cj.jdbc.Driver");// ### 建立连接Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?characterEncoding=utf-8","root", "root");// ### 获取发送SQL的对象Statement statement = conn.createStatement();// ### 执行SQLString sql = "insert into account (id,name,money) values (5,'赵六',9999)";int count = statement.executeUpdate(sql);// ### 处理结果if (count == 1) {System.out.println("当前操作成功!");}
// ### 3.3.6 释放资源statement.close();conn.close();}}
常见错误


ResultSet结果集
ResultSet操作
前面操作是针对增删改,返回结果是几行受影响,就是一个int类型的数值。
现在需要玩一波查询操作,而查询操作,返回的就是一个虚拟表。
直接查询之前test库中的account表
首先在执行查询的select的SQL语句时,需要使用的是statement提供的executeQuery方法。
其次,在执行executeQuery方法后,返回的是一个ResultSet结果集,他相当你查询的数据内容。
再有就是针对ResultSet的操作。首先要记住ResultSet的next方法。
next方法类似一个指针,你每次next,指针都会移动到下一行。如果下一行有数据,next方法会返回true,如果下一行没数据,next方法会返回false。
Ps:ResultSet第一次执行next,指针才会指向第一行。
在指针指向某一个行之后,可以再基于ResultSet提供的getXxx方法获取对应列的数据,获取对应列的方式,可以通过序号来找,从1开始,但是 推荐使用列名去找具体数据 。
package com.jimihua;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;/*** 查询account表,获取返回的结果集ResultSet*/
public class Demo2 {public static void main(String[] args) throws Exception {//1、注册驱动Class.forName("com.mysql.cj.jdbc.Driver");//2、获取连接Connection conn =DriverManager.getConnection("jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8","root","root");//3、获取StatementStatement statement = conn.createStatement();//4、执行查询的SQLString sql = "select * from account";ResultSet rs = statement.executeQuery(sql);//5、操作ResultSet结果集//5.1 先用ResultSet的一个next方法确认是否有返回的数据while(rs.next()){// 如果进到while循环,说明有数据// 5.2 基于ResultSet提供的get类型方法去获取结果long id = rs.getLong("id");String name = rs.getString("name");long money = rs.getLong("money");System.out.println("获取数据:" + id + "," + name + "," + money + "。");}// 到这,说明指针已经到最后了,没有数据了。//6、释放资源rs.close();statement.close();conn.close();}
}
常见错误

综合案例
完成一个注册登录的小案例。
准备表
创建一张用户表user
- id,数值类型,主键,自增
- username,用户名,字符串类型,唯一,非空
- password,密码,字符串类型,非空
create table user(id bigint primary key auto_increment comment '主键id',username varchar(32) unique not null comment '用户名',password varchar(32) not null comment '密码' )comment '用户表';查询2条测试数据
insert into user values (1,'admin','admin'),(2,'zhangsan','123456');
实现注册和登录操作
注册驱动这个事情,只需要做一次就足够了。
注册驱动的本质就是将MySQL的Driver对象存放到DriverManager中的一个List集合中。
package com.jimihua;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Scanner;/*** 实现注册和登录操作*/
public class Demo3 {public static void main(String[] args) throws Exception {// 因为注册驱动的操作,做一次就够了,他就是将Driver的对象扔到DriverManager的一个List集合中Class.forName("com.mysql.cj.jdbc.Driver");Scanner input = new Scanner(System.in);while(true){// 基于提示,做具体什么操作System.out.println("当前可以选择注册或者登录");System.out.println("注册操作输入 1");System.out.println("登录操作输入 2");int i = input.nextInt();// 因为无论是注册还是登录,都需要用户输入用户名和密码System.out.println("请输入用户名:");String username = input.next();System.out.println("请输入密码:");String password = input.next();// 根据i执行不同的逻辑if(i == 1){// 注册操作//1、获取链接Connection conn =DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbc_test?characterEncoding=UTF-8", "root", "root");//2、拿到statementStatement statement = conn.createStatement();//3、准备注册的insert的SQLString sql = "insert into user (username,password) values ('"+username+"','"+password+"');";System.out.println("注册要执行的SQL:" + sql);//4、执行SQLint count = statement.executeUpdate(sql);//5、根据返回结果基于提示if(count == 1){System.out.println("注册成功!!");}//6、释放资源statement.close();conn.close();}else {// 登录操作//1、获取链接Connection conn =DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbc_test?characterEncoding=UTF-8", "root", "root");//2、拿到statementStatement statement = conn.createStatement();//3、准备登录的查询SQLString sql = "select * from user where username='"+username+"' and password='"+password+"';";System.out.println("登录要执行的SQL:" + sql);//4、执行SQLResultSet resultSet = statement.executeQuery(sql);if (resultSet.next()){// 到这,说明用户名和密码正确,登录成功!System.out.println("用户名和密码正确,登录成功!");}else{// 到这,说明用户名和密码错误,登录失败!System.out.println("用户名和密码错误,登录失败!");}//5、释放资源resultSet.close();statement.close();conn.close();}}}
}
SQL注入问题
问题介绍
用户输入的数据中有SQL关键字或者语法,并且这些内容参与了SQL语句的编译,导致SQL语句编译后的条件含义为true,一致得到正确的结果,你输入的内容其实不是正确的。这种现象就成为 SQL注入 。

SQL注入是一个很经典的问题。 由于编写的SQL语句是在用户输入数据,整合后再进行编译的。所以为了避免SQL注入的问题,咱们要使SQL语句在用户输入数据前,就已经编译完成了完整的SQL语句,再进行填充数据。
PreparedStatement
PreparedStatement实现了Statement接口,执行SQL语句的方法,和最开始使用的Statement对象是一样的。
之前通过createStatement方法获取到的是
public class StatementImpl现在需要使用到的是,PreparedStatement的实现类
public interface PreparedStatement咱们也在PreparedStatement接口上的注释信息看到了基本的使用方式
将SQL语句中需要咱们填充的值,采用?代替,然后再通过PreparedStatement对象的setXxx方法,通过从1开始的索引位置,给每个?赋值。
PreparedStatement pstmt = con.prepareStatement("UPDATE EMPLOYEES SET SALARY = ? WHERE ID = ?"); pstmt.setBigDecimal(1, 153833.00) pstmt.setInt(2, 110592)
将前面的综合案例修改为使用PreparedStatement对象来解决之前的问题
package com.jimihua;
import java.sql.*;
import java.util.Scanner;/*** 实现注册和登录操作* 基于SQL注入的问题,在这里采用PreparedStatement来解决SQL注入问题。*/
public class Demo4 {public static void main(String[] args) throws Exception {// 因为注册驱动的操作,做一次就够了,他就是将Driver的对象扔到DriverManager的一个List集合中Class.forName("com.mysql.cj.jdbc.Driver");Scanner input = new Scanner(System.in);while(true){// 基于提示,做具体什么操作System.out.println("当前可以选择注册或者登录");System.out.println("注册操作输入 1");System.out.println("登录操作输入 2");int i = input.nextInt();// 因为无论是注册还是登录,都需要用户输入用户名和密码System.out.println("请输入用户名:");String username = input.next();System.out.println("请输入密码:");String password = input.next();// 根据i执行不同的逻辑if(i == 1){// 注册操作//1、获取链接Connection conn =DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbc_test?characterEncoding=UTF-8", "root", "root");//2、准备注册的insert的SQLString sql = "insert into user (username,password) values (?,?)";//3.1、拿到statementPreparedStatement ps = conn.prepareStatement(sql);//3.2 给占位符?赋值ps.setString(1,username);ps.setString(2,password);//4、执行SQLint count = ps.executeUpdate();//5、根据返回结果基于提示if(count == 1){System.out.println("注册成功!!");}//6、释放资源ps.close();conn.close();}else {// 登录操作//1、获取链接Connection conn =DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbc_test?characterEncoding=UTF-8", "root", "root");//2、准备登录的查询SQLString sql = "select * from user where username = ? and password = ?";//3.1、拿到statementPreparedStatement ps = conn.prepareStatement(sql);//3.2、给?赋值ps.setString(1,username);ps.setString(2,password);//4、执行SQLResultSet resultSet = ps.executeQuery();if (resultSet.next()){// 到这,说明用户名和密码正确,登录成功!System.out.println("用户名和密码正确,登录成功!");}else{// 到这,说明用户名和密码错误,登录失败!System.out.println("用户名和密码错误,登录失败!");}//5、释放资源resultSet.close();ps.close();conn.close();}}}
}
相关文章:
java程序员入行科目一之CRUD轻松入门教程(一)
之前在操作MySQL的时候,都是采用Navicat,或者cmd黑窗口。 无论使用什么方式和MySQL交互,大致步骤是这样的 建立连接,需要输入用户名和密码编写SQL语句,和数据库进行交互 这个连接方式不会变,但是现在需要 基…...
OpenHarmony鸿蒙开发( Beta5.0)智能油烟机开发实践
样例简介 本Demo是基于Hi3516开发板,使用开源OpenHarmony开发的应用。本应用主要功能有: 可以搜索本地指定目录的图片和视频文件,并可进行点击播放。 可以通过wifi接收来自手机的美食图片以及菜谱视频,让我们对美食可以边学边做…...
【GBase 8c V5_3.0.0 分布式数据库常用维护命令】
一、查看数据库状态/检查(gbase用户) 1.gha_ctl monitor 使用gha_ctl monitor查看节点运行情况(跟dcs的地址和端口) gha_ctl monitor -c gbase -l http://172.20.10.8:2379 -Hall |coordinator | datanode | gtm | server|dcs:必选字段。指定查看哪类集…...
破解AI生成检测:如何用ChatGPT降低论文的AIGC率
学境思源,一键生成论文初稿: AcademicIdeas - 学境思源AI论文写作 降低论文的“AIGC率”是个挑战,但有一些策略可以尝试。使用ChatGPT逐步调整和改进内容,使其更加自然和原创,降低AI检测工具识别出高“AIGC率”的概率…...
Python用MarkovRNN马尔可夫递归神经网络建模序列数据t-SNE可视化研究
原文链接:https://tecdat.cn/?p37634 本文聚焦于利用马尔可夫递归神经网络(MarkovRNN)结合树库展开建模工作。MarkovRNN 通过整合马尔可夫特性与离散随机变量来深入探索递归神经网络中的随机转换机制,旨在高效处理具有复杂潜在信…...
setup函数子传父普通写法
父组件 <template><div><p>接收的数据: {{ receivedData }}</p><Demo4Chiren2 custom-event"handleGetWeb" /></div> </template><script> import { ref } from vue; import Demo4Chiren2 from ./demo4Chiren2.vue…...
seafaring靶场漏洞测试攻略
步骤一:打开网页 一:sql注入漏洞 步骤一:测试回显点 -1 union select 1,2,3# 步骤二:查看数据库 -1 union select 1,2,database()# 步骤三:查看表名 -1 union select 1,2,group_concat(table_name) from informati…...
简单示例,搞懂PowerBI的ALL(),ALLEXCEPT()和ALLSELECTED()的区别
假设我们有如下数据,我们来统计下各班级的人数 我们在报表页里加上 班级’二班‘ 的筛选条件,此时PowerBI已经自动为我们显示了各班级人数:一班有3人,二班有1人。 根据我们的筛选条件,我们的统计人数应该是按照筛选器&…...
Collection
java.util.Collections:是集合工具类 作用:Collections不是集合,而是集合的工具类 常用API addAll package Collections;import java.util.ArrayList; import java.util.Collections;public class CollectionsDemo {public static void main(String[]…...
19章 泛型
1.修改程序清单19-1中的GenericStack类,使用数组而不是ArrayList来实现它。你应该在给栈添加新元素之前检查数组的大小如果数组满了,就创建一个新数组。该数组是当前数组大小的两倍,然后将当前数组的元素复制到新数组中。 public class Gene…...
基于python+django+mysql+Nanodet检测模型的水稻虫害检测系统
博主介绍: 大家好,本人精通Java、Python、C#、C、C编程语言,同时也熟练掌握微信小程序、Php和Android等技术,能够为大家提供全方位的技术支持和交流。 我有丰富的成品Java、Python、C#毕设项目经验,能够为学生提供各类…...
计算机网络27、28——Linux命令1、2
1、虚拟机网络前方路径内容 用户名机器名:/$ $表示普通用户,#表示root用户 2、Linux不分盘,都是绝对路径 /表示根目录,表示计算机文件夹下 ~是当前用户的家,表示home文件夹下自己的文件夹 3、bin文件夹下的是可执…...
【Python深度学习】逆强化学习(IRL):通俗揭开学习背后的奥秘
逆强化学习:揭开学习背后的奥秘 1. 引言 当我们谈论人工智能(AI)时,很多人第一时间会想到强化学习。强化学习是一种让智能体通过与环境的互动,逐渐学习到如何做出最优决策的学习方法。然而,有一种更加神奇的学习方式叫做 逆强化学习(Inverse Reinforcement Learning,…...
Linux:五种IO模型
1:五种IO模型 1:阻塞IO 阻塞IO: 在内核将数据准备好之前,系统调用会一直等待.所有的套接字,默认 都是阻塞方式。 2:非阻塞 IO 非阻塞 IO: 如果内核还未将数据准备好, 系统调用仍然会直接返回, 并且返回EWOULDBLOCK 错误码。 非阻塞 IO 往往需…...
ansible企业实战
ansible最佳实践 优化ansible速度 开启SSH长连接 修改 /etc/ansible/ansible.cfg里面的参数 ssh_args -C -o ControlMasterauto -o ControlPersist5d ControlPersist5d这个参数是设置整个长连接保持时间设置为5天,如果开启,通过SSH连接过的设备都会…...
面向对象程序设计之模板进阶(C++)
在之前我出过一篇博客介绍了模版的初阶:面向对象程序设计(C)模版初阶,接下来我们将进行模版的进阶学习,介绍关于更多模版的知识 1.非类型模版参数 模板参数分类类型形参与非类型形参 类型形参即:出现在模板参数列表中,跟在class或…...
电巢科技携Ecosmos元宇宙产品亮相第25届中国光博会
第25届中国国际光电博览会(“CIOE中国光博会”)今日在深圳国际会展中心盛大开幕。本届博览会以“光电引领未来,驱动应用创新”为主题,吸引了全球超过3700家优质光电企业参展,展示了光电产业的最新成果和前沿技术。 电…...
Redis 入门 - 收官
《Redis 入门》系列文章总算完成了,希望这个系列文章可以想入门或刚入门的同学提供帮助,希望能让你形成学习Redis系统性概念。 当时为什么要写这个系列文章,是因为我自己就是迷迷糊糊一路踩坑走过来的,我踩完的坑就踩完了&#x…...
Windows技术栈企业基础底座(1)-为基于Windows的Nginx安装证书
企业的基础环境是一个组织的信息化数字化底座。传统企业基础环境多种系统,应用交杂,多种技术栈使得深入运维成本极大,且人员知识技能较难复用,造成资源浪费。本系列旨在尝试推动这一理念, 建立Windows, 或linux聚焦的技术栈的企业…...
ThreeJS入门(002):学习思维路径
查看本专栏目录 - 本文是第 002篇入门文章 文章目录 如何使用这个思维导图 Three.js 学习思维导图可以帮助你系统地了解 Three.js 的各个组成部分及其关系。下面是一个简化的 Three.js 学习路径思维导图概述,它包含了学习 Three.js 的主要概念和组件。你可以根据这个…...
ssc377d修改flash分区大小
1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...
【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...
Angular微前端架构:Module Federation + ngx-build-plus (Webpack)
以下是一个完整的 Angular 微前端示例,其中使用的是 Module Federation 和 npx-build-plus 实现了主应用(Shell)与子应用(Remote)的集成。 🛠️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...
HubSpot推出与ChatGPT的深度集成引发兴奋与担忧
上周三,HubSpot宣布已构建与ChatGPT的深度集成,这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋,但同时也存在一些关于数据安全的担忧。 许多网络声音声称,这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...
「全栈技术解析」推客小程序系统开发:从架构设计到裂变增长的完整解决方案
在移动互联网营销竞争白热化的当下,推客小程序系统凭借其裂变传播、精准营销等特性,成为企业抢占市场的利器。本文将深度解析推客小程序系统开发的核心技术与实现路径,助力开发者打造具有市场竞争力的营销工具。 一、系统核心功能架构&…...
永磁同步电机无速度算法--基于卡尔曼滤波器的滑模观测器
一、原理介绍 传统滑模观测器采用如下结构: 传统SMO中LPF会带来相位延迟和幅值衰减,并且需要额外的相位补偿。 采用扩展卡尔曼滤波器代替常用低通滤波器(LPF),可以去除高次谐波,并且不用相位补偿就可以获得一个误差较小的转子位…...
Sklearn 机器学习 缺失值处理 获取填充失值的统计值
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 使用 Scikit-learn 处理缺失值并提取填充统计信息的完整指南 在机器学习项目中,数据清…...
云安全与网络安全:核心区别与协同作用解析
在数字化转型的浪潮中,云安全与网络安全作为信息安全的两大支柱,常被混淆但本质不同。本文将从概念、责任分工、技术手段、威胁类型等维度深入解析两者的差异,并探讨它们的协同作用。 一、核心区别 定义与范围 网络安全:聚焦于保…...
倒装芯片凸点成型工艺
UBM(Under Bump Metallization)与Bump(焊球)形成工艺流程。我们可以将整张流程图分为三大阶段来理解: 🔧 一、UBM(Under Bump Metallization)工艺流程(黄色区域ÿ…...
[特殊字符] 手撸 Redis 互斥锁那些坑
📖 手撸 Redis 互斥锁那些坑 最近搞业务遇到高并发下同一个 key 的互斥操作,想实现分布式环境下的互斥锁。于是私下顺手手撸了个基于 Redis 的简单互斥锁,也顺便跟 Redisson 的 RLock 机制对比了下,记录一波,别踩我踩过…...

