java程序员入行科目一之CRUD轻松入门教程(一)

news2024/11/24 11:55:32

之前在操作MySQL的时候,都是采用Navicat,或者cmd黑窗口。

无论使用什么方式和MySQL交互,大致步骤是这样的

  • 建立连接,需要输入用户名和密码
  • 编写SQL语句,和数据库进行交互

这个连接方式不会变,但是现在需要 基于Java语言去和MySQL进行一波

image.png

在实际开发中,当用户要对数据进行一些改变的时候,不能通过工具去执行SQL或者直接点来点去修改的,需要用Java语言去进行交互,使用Java会让操作更有效率和准确性。

Java语言为了提供和多种数据库都可以用一样的方式进行交互,Java提供了一个规范,这个规范 JDBC(Java Database Connectivity)

JDBC介绍

什么是JDBC

JDBC就是Java对外提供的一种规范,JDBC的目的就是让Java语言可以和数据库进行交互,完成CRUD。

JDBC的核心思想

JDBC是个规范,Java就对外发布了这个规范,如果各个数据库厂商,想让你的数据库可以和Java进行交互,数据库厂商就需要根据我JDBC的规范去做具体的实现,提供一个驱动(Driver)。

image.png

MySQL数据库驱动

这里在课程资料中会提供,如果想自行下载,可以去一个地址搜索。

http://mvnrepository.com

可以直接搜索需要的jar包,只要大版本没问题,正常下载即可

image.png

JDBC API

JDBC的API主要掌握4个,了解1个。

类型类的全路径描述
classjava.sql.DriverManager管理数据库的驱动类,需要基于他来获取到Connection连接对象
interfacejava.sql.Connection代表一个和数据库的连接,通过他获取到Statement发送SQL
interfacejava.sql.Statement将SQL语句发送给数据库服务端
interfacejava.sql.ResultSet数据库服务端执行完毕SQL后的返回结果
classjava.sql.SQLException和数据库交互时,会抛出的异常。

JDBC开发步骤

构建项目

image.png

导入依赖

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

image.png

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

image.png

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

image.png

编写开发过程

注册驱动

//        ###  注册驱动
// 本质就是将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();

//        ###  执行SQL
        String 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();
    }

}

常见错误

image.png


image.png


image.pngResultSet结果集

ResultSet操作

前面操作是针对增删改,返回结果是几行受影响,就是一个int类型的数值。

现在需要玩一波查询操作,而查询操作,返回的就是一个虚拟表。

直接查询之前test库中的account表

首先在执行查询的select的SQL语句时,需要使用的是statement提供的executeQuery方法。

其次,在执行executeQuery方法后,返回的是一个ResultSet结果集,他相当你查询的数据内容。

image.png

再有就是针对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、获取Statement
        Statement statement = conn.createStatement();

        //4、执行查询的SQL
        String 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();
    }
}

常见错误

image.png

综合案例

完成一个注册登录的小案例。

准备表

创建一张用户表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、拿到statement
                Statement statement = conn.createStatement();
                //3、准备注册的insert的SQL
                String sql = "insert into user (username,password) values ('"+username+"','"+password+"');";
                System.out.println("注册要执行的SQL:" + sql);
                //4、执行SQL
                int 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、拿到statement
                Statement statement = conn.createStatement();
                //3、准备登录的查询SQL
                String sql = "select * from user where username='"+username+"' and password='"+password+"';";
                System.out.println("登录要执行的SQL:" + sql);
                //4、执行SQL
                ResultSet 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注入

image.png

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的SQL
                String sql = "insert into user (username,password) values (?,?)";
                //3.1、拿到statement
                PreparedStatement ps = conn.prepareStatement(sql);
                //3.2 给占位符?赋值
                ps.setString(1,username);
                ps.setString(2,password);
                //4、执行SQL
                int 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、准备登录的查询SQL
                String sql = "select * from user where username = ? and password = ?";

                //3.1、拿到statement
                PreparedStatement ps = conn.prepareStatement(sql);
                //3.2、给?赋值
                ps.setString(1,username);
                ps.setString(2,password);

                //4、执行SQL
                ResultSet resultSet = ps.executeQuery();
                if (resultSet.next()){
                    // 到这,说明用户名和密码正确,登录成功!
                    System.out.println("用户名和密码正确,登录成功!");
                }else{
                    // 到这,说明用户名和密码错误,登录失败!
                    System.out.println("用户名和密码错误,登录失败!");
                }
                //5、释放资源
                resultSet.close();
                ps.close();
                conn.close();

            }
        }
    }
}

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

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

相关文章

苹果系统(MacOS)中的Finder如何方便展现根目录

前言 初用Finder的时候,感觉非常的不方便。没有Windows的文件管理器来的简单明了。 本文,就是针对找不到文件根目录和隐藏文件夹的设置,进行了说明,供大家参考。 1、设置前 打开Finder,看不到DISK,也就是…

理解前向传播、反向传播和计算图

1. 什么是前向传播? 前向传播(Forward Propagation)是神经网络的推理过程。它将输入数据逐层传递,通过每一层的神经元计算,最终生成输出。 前向传播的公式 假设我们有一个简单的三层神经网络(输入层、一…

一种简单的过某宝验证码的方式(仅做学习使用)

开篇 今天介绍一种简单的过某宝验证码的方式,用的是自动化,这样对不会js逆向的小白非常友好,只需要用到selenium框架就能轻松过某宝验证码,即模拟人的操作对滑块进行滑动。 但是首先还是需要训练验证码和标题 训练前&#xff1a…

各个大厂软件测试面试题,面试经验分享

前言 一、华为测试岗电话面试 一面 1)自我介绍 2)项目流程 >讲下H模型 3)业务流程 >项目讲解、可从贷款流程讲起 4)做过自动化吗? 5)做过接口测试吗? 可从postman和jmeter做手工接口测…

数业智能心大陆探索生成式AIGC创新前沿

近日,数业智能心大陆参与了第九届“创客中国”生成式人工智能(AIGC)中小企业创新创业大赛。在这场汇聚了众多创新力量的研讨过程中,广东数业智能科技有限公司基于多智能体的心理健康技术探索与应用成果,从众多参赛者中…

KTM580030bit 绝对角度细分器支持最多 4096 对极与一键非线性自校准集成双 16bit 2M SAR ADC

KTM5800 是一款 30bit 绝对角度细分 4096 对极编码细分器,可以与磁电阻传感器( AM R/TMR )搭配,构成一个高速高精度的非接触磁性编码器模块。它具有以非常高的采样速率 读取传感器上的差分模拟正弦和余弦信号的能力&#xf…

vue3提交按钮限制重复点击

下载lodash npm install lodash 引入并使用 <template><div click"submit()">提交</div> </template><script setup>import { debounce } from lodash;const submit debounce(() > {//业务代码},2000,{leading: true,trailing:…

ETL数据集成丨建设BI的关键前提是ETL数据集成?

背景 很多企业都购买了商业智能&#xff08;BI&#xff09;来加速数字化转型&#xff0c;但是发现仅仅依赖BI效果往往不太好。虽然通过BI&#xff0c;企业能够快速分析和可视化数据&#xff0c;然而&#xff0c;BI并不是一个万能工具&#xff0c;它虽然能帮助企业解读数据&…

rancker 图形化界面

rancker 图形化界面 图形化界面进行k8s集群的管理 rancher自带监控————普罗米修斯 #在master和两个node上都操作 [rootmaster01 opt]# rz -E rz waiting to receive. [rootmaster01 opt]# docker load -i rancher.tar ​ #在master上操作 [rootmaster01 opt]# docker pul…

90v转5v500MA内置mos芯片方案

在设计一个90V转5V500mA的DC/DC转换器方案时&#xff0c;可以考虑使用AH7550这款150KHz固定频率PWM降压&#xff08;降压&#xff09;DC/DC转换器。AH7550能够以高效率、低纹波和出色的线路和负载调节驱动0.4A负载&#xff0c;且需要最少数量的外部组件&#xff0c;使用简单&am…

【物联网技术大作业】设计一个智能家居的应用场景

前言&#xff1a; 本人的物联网技术的期末大作业&#xff0c;希望对你有帮助。 目录 大作业设计题 &#xff08;1&#xff09;智能家居的概述。 &#xff08;2&#xff09;介绍智能家居应用。要求至少5个方面的应用&#xff0c;包括每个应用所采用的设备&#xff0c;性能&am…

CAPL_构建基于UDS的刷写学习—01 Hex文件的解析

前言&#xff1a; 打算写一个系列&#xff1a;CAPL_构建基于UDS的刷写学习&#xff0c;大致写一下写作的思路 1&#xff1a;本文是第1篇首先讲解基础。首先搞清楚&#xff0c;各种不同文件&#xff08;常见的S19,hex,bin,以及汽车行业主机厂自己的各种文件CBF(奇瑞特有),VBF&…

SpringCloud Alibaba之Nacos服务注册和配置中心

&#xff08;学习笔记&#xff09;nacos-server版本&#xff1a;2.2.3 总体介绍&#xff1a; 1、Nacos介绍 官网&#xff1a;Nacos官网| Nacos 配置中心 | Nacos 下载| Nacos 官方社区 | Nacos 官网 Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service的首字…

8路模拟量采集模块,4~20mA 0~10V电流电压高速采集——DAM-3054P

阿尔泰科技 DAM-3054P为8路差分模拟量采集模块&#xff0c;高速采集&#xff0c;每通道采集速率为500sps&#xff0c;16位AD&#xff0c;支持RS485通讯接口&#xff0c;带有标准ModbusRTU协议。配备良好的人机交互界面&#xff0c;使用方便&#xff0c;性能稳定。 指标参数&…

基于图像的端到端方案实现小车在模拟城市场景中的自主导航

基于图像的端到端方案实现小车在模拟城市场景中的自主导航 FSD&#xff08;Full Self-Driving&#xff09;是特斯拉公司推出的一种自动驾驶技术&#xff0c;旨在实现完全自主的驾驶体验。FSD系统依靠大量的数据和高级的机器学习算法&#xff0c;结合车载传感器&#xff08;如摄…

docker--刚开始学不知道如何操作拉取,或拉取失败(cmd)

报 unauthorized: incorrect username or password.&#xff08;未授权&#xff09; 进行授权 在docker desktop注册账号登录好docker desktop 在cmd中进行docker登录&#xff0c;输入账号密码&#xff0c;提示Login Succeeded&#xff0c;即登录成功 docker login -u xxx(x…

yjs04——matplotlib的使用(多个坐标图)

1.多个坐标图与一个图的折线对比 1.引入包&#xff1b;字体&#xff08;同&#xff09; import matplotlib.pyplot as plt import random plt.rcParams[font.family] [SimHei] plt.rcParams[axes.unicode_minus] False 2.创建幕布 2.1建立图层幕布 一个图&#xff1a;plt.fig…

Artec Leo协助定制维修管道,让石油和天然气炼油厂不停产

以下文章来源于Artec3D埃太科三维 &#xff0c;作者小埃 挑战 在高温、狭窄的炼油厂中&#xff0c;准确测量结构复杂的受损管道和设备&#xff0c;以便设计、制造、安装定制维修解决方案&#xff0c;从而尽快完成修复。 解决方案 Artec Leo, Artec Studio, Geomagic Design X…

关于Vue2里 v-for和v-if一起用的时候会出现的问题

关于Vue2里 v-for和v-if一起用的时候会出现的问题 &#x1f389;&#x1f389;&#x1f389;欢迎来到我的博客,我是一名自学了2年半前端的大一学生,熟悉的技术是JavaScript与Vue.目前正在往全栈方向前进, 如果我的博客给您带来了帮助欢迎您关注我,我将会持续不断的更新文章!!!&…

roboguide将tp程序转化为LS文本格式的方法

不同的软件版本可能操作不同&#xff0c;但是仍然可以参考文章中的办法。 我使用的版本如图所示&#xff1a; 1.首先&#xff0c;打开任意一个工程&#xff0c;如果没有&#xff0c;可以打开自带的示例。 如图&#xff0c;我打开了自带的示例&#xff0c;在帮助文档中可以找到…