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个。

类型 类的全路径 描述
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开发步骤

构建项目

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();

            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/jbjmh/article/details/142219161