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

之前在操作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();

            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鷄米花

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值