数据库
首页 > 数据库> > MYSQL的Java操作器——JDBC

MYSQL的Java操作器——JDBC

作者:互联网

MYSQL的Java操作器——JDBC

在学习了Mysql之后,我们就要把Mysql和我们之前所学习的Java所结合起来

而JDBC就是这样一种工具:帮助我们使用Java语言来操作Mysql数据库

JDBC简介

首先我们先来了解一下JDBC

JDBC概念:

JDBC本质:

JDBC优点:

JDBC快速入门

下面我们通过JDBC的基本步骤和一段实例代码来带大家体验一下JDBC

基本步骤:

// 0.创建工程,导入驱动jar包 (资源可以在网络搜索)
    
// 1.注册驱动
    Class.forName("com.mysql.jdbc.Driver");
// 2.获得连接
    Connection conn = DriverManager.getConnection(url,username,password);
// 3.定义MYSQL语句
    String sql = "~~~";
// 4.获得执行对象
    Statement stmt = conn.createStatement();
// 5.执行SQL语句
    stmt.executeUpdate(sql);
// 6.处理返回结果
    
// 7.释放资源

实例代码:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

// JDBC快速入门
public class Demo1 {

    public static void main(String[] arg) throws Exception{

        //  1.注册驱动(这里是固定语法,是Java中的反射)
        Class.forName("com.mysql.jdbc.Driver");

        //  2.获得连接(Connection是类,最后需要释放资源)
        //  (url前面固定jdbc:mysql://127.0.0.1:3306/,最后加上你所需要的数据库test,username为数据库账号,password为数据库密码)
        String url = "jdbc:mysql://127.0.0.1:3306/test";
        String username = "root";
        String password = "123456";
        Connection conn = DriverManager.getConnection(url,username,password);

        //   3.定义SQL语句(这里SQL语句与MYSQL语句相同)
        String sql = "update jdbc_test set age = 20 where id = 1";

        //   4.获得执行SQL对象(这里也是类)
        Statement stmt = conn.createStatement();

        //   5.执行SQL(注意这里返回的是count,是sql中受影响的行数)
        int count = stmt.executeUpdate(sql);

        //   6.返回执行结果
        System.out.println(count);

        //   7.释放内存
        stmt.close();
        conn.close();
    }
}

JDBC API详解

JDBC中的API主要有四种,我们将在下面一一介绍:

DriverManager

DriverManager主要包含两个作用:

  1. 注册驱动
// 注册驱动是JDBC使用的第一步
Class.forName("com.mysql.jdbc.Driver");
// 上述的操作虽然是Class类的forName操作,但实际上是由Driver类的static函数组成的,如果含兴趣可以上网搜索该代码

注意:

  1. 获取连接
//  2.获得连接
//  (url前面固定jdbc:mysql://127.0.0.1:3306/,最后加上你所需要的数据库test,username为数据库账号,password为数据库密码)

String url = "jdbc:mysql://127.0.0.1:3306/test";
String username = "root";
String password = "123456";
Connection conn = DriverManager.getConnection(url,username,password);

这里getConnection包含三个参数,username和password分别表示账号和密码,不需要解释

我们主要关注url的构造:

// 语法: jdbc:mysql://ip地址(域名):端口号/数据库名称?参数键值对1&参数键值对2...

// 实例: String url = "jdbc:mysql://127.0.0.1:3306/test?useSSL=false";

注意:

最后我们给出整体代码来展现DriverManager所学到的部分:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

// JDBC_DriverManager
public class Demo2 {

    public static void main(String[] arg) throws Exception{

        // 我们在MYSQL5.0以上版本可以省略注册驱动的步骤
        // Class.forName("com.mysql.jdbc.Driver");

        // 当我们在主机使用MYSQL时,可以省略27.0.0.1:3306
        // 如果我们希望省略SSL警告语言可以设置关闭
        String url = "jdbc:mysql:///test?useSSL=false";
        String username = "root";
        String password = "123456";
        Connection conn = DriverManager.getConnection(url,username,password);

        String sql = "update jdbc_test set age = 20 where id = 1";

        Statement stmt = conn.createStatement();

        int count = stmt.executeUpdate(sql);

        System.out.println(count);

        stmt.close();
        conn.close();
    }
}

Connection

Connection主要包含两个作用:

  1. 获得执行SQL对象

我们有三种方法可以获得SQL执行对象,这里先做出语法介绍,在后续我们会进行详细解释:

Statement stmt = conn.createStatement();
PreparedStatement pstmt = conn.prepareStatement(sql);
CallableStatement cstmt = conn,prepareCall(sql);
  1. 事务管理

我们可以通过Connection来进行MYSQL中的事务管理

我们通过对比MYSQL的事务来解释:

# 开启事务
BEGIN;

# 提交事务
COMMIT;

# 回滚事务
ROLLBACK;

-- mysql自动提交事务

我们的JDBC也同样提供三种方法来对应mysql事务:

// 开启事务 boolean autoCommit有两种选择:true为自动提交,false为手动提交(如果希望手动提交设置为false)
conn.setAutoCommit(boolean autoCommit)

// 提交事务
conn.commit();

// 回滚事务
conn.rollback();

最后我们给出整体代码来展现Connection所学到的部分:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

// JDBC_Connection
public class Demo3 {

    public static void main(String[] arg) throws Exception{

        String url = "jdbc:mysql:///test?useSSL=false";
        String username = "root";
        String password = "123456";
        Connection conn = DriverManager.getConnection(url,username,password);

        // 我们来研究事务的执行 (我们希望下面两条语句在一个事务中同时执行)
        String sql1 = "update jdbc_test set age = 16 where id = 1";
        String sql2 = "update jdbc_test set age = 16 where id = 2";

        Statement stmt = conn.createStatement();

        // 我们需要在try中进行,因为为了当出错时可以采用回滚方法
        try {
            // 开启事务
            conn.setAutoCommit(false);

            int count1 = stmt.executeUpdate(sql1);

            System.out.println(count1);

            int count2 = stmt.executeUpdate(sql2);

            System.out.println(count2);

            // 提交事务
            conn.commit();

        } catch (Exception e){
            // 出错时回滚事务
            conn.rollback();
        }

        stmt.close();
        conn.close();
    }
}

Statement

Statement只有一个作用:执行SQL语句

Statement的执行方式主要分为两种:

  1. executeUpdate(DML,DDL)

Statement可以执行Update操作,主要针对mysql的DML和DDL操作

// 下述是Statement执行DML和DDL操作的语法,sql为String类型的mysql语句

int count = stmt.executeUpdate(sql);

// 注意:返回值是DML和DDL语句所影响的行数

下面我们给出整体案例解释Statement的executeUpdate操作:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

// JDBC_DriverManager
public class Demo4 {

    public static void main(String[] arg) throws Exception{


    }

    public static void test_DML() throws SQLException {

        String url = "jdbc:mysql:///test?useSSL=false";
        String username = "root";
        String password = "123456";
        Connection conn = DriverManager.getConnection(url,username,password);

        String sql = "update jdbc_test set age = 20 where id = 1";

        Statement stmt = conn.createStatement();

        int count = stmt.executeUpdate(sql);

        // 我们在实际页面制作时,需要给用户反馈是否成功
        // 对于DML语句,当count>0时基本为操作成功

        if(count>0){
            System.out.println("操作成功!");
        }else {
            System.out.println("操作失败~");
        }

        stmt.close();
        conn.close();
    }

    public static void test_DDL() throws SQLException {

        String url = "jdbc:mysql:///test?useSSL=false";
        String username = "root";
        String password = "123456";
        Connection conn = DriverManager.getConnection(url,username,password);

        String sql = "update jdbc_test set age = 20 where id = 1";

        Statement stmt = conn.createStatement();

        int count = stmt.executeUpdate(sql);

        // 我们在实际页面制作时,需要给用户反馈是否成功
        // 对于DDL语句,DROP时count为0,所以不能用count判断,基本情况下不报错即为成功

        stmt.close();
        conn.close();
    }
}
  1. executeQuery(DQL)

Statement可以执行Query操作,主要针对mysql的DQL操作

// 下述是Statement执行DQL操作的语法,sql为String类型的mysql语句
ResultSet resultSet = stmt.executeQuery(sql);

// 注意:ResultSet是stmt.executeQuery的返回类型,下面我们将着重介绍一下

ResultSet的作用:

那么如何获得ResultSet所储存的值:

// ResultSet具有next()方法,其作用是:将当前光标向前移动一行,并判断当前行是否为有效行并返回true或false
// ResultSet在获得结果后的光标指向目录行,移动一行后得到第一行数据,
boolean next():

/*
true:表示当前行有数据,可以提取或者直接输出搜索成功
false:表示当前行没有数据,表示搜索失败
*/
// ResultSet具有getXxx(参数)方法,其作用是获得当前行保存的数据
Xxx name = resultSet.getXxx(参数);

/*
Xxx 表示数据类型:Int,Double,String等
参数有两种:
	1.数字参数,表示列数
	2.字符串参数,表示列名
*/
// 具体遍历采用while语法
while(rs.next()){
    //获得数据
    int i = rs.getInt(1);
}

下面我们给出整体案例解释Statement的executeQuery操作:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

// JDBC_SQL
public class Demo5 {

    public static void main(String[] arg) throws Exception{

        String url = "jdbc:mysql://127.0.0.1:3306/test?useSSL=false";
        String username = "root";
        String password = "123456";
        Connection conn = DriverManager.getConnection(url,username,password);

        // 我们接下来讲解SQL,因为SQL所获得的数据类型为ResultSet,所以我们单独讲解

        // 先设置SQL语句
        String sql = "select * from jdbc_test";

        // 然后获得对象
        Statement stmt = conn.createStatement();

        // 然后开始执行语句
        ResultSet resultSet = stmt.executeQuery(sql);

        // 然后我们循环得到数据

        // next最开始指向非数据行,然后开始执行:向下运行一行,并且判断是否为有效行
        while (resultSet.next()){
            // 当为有效行,获得数据(可以通过列数,也可以通过列名)
            int id = resultSet.getInt("id");
            String string = resultSet.getString(2);
            int age = resultSet.getInt("age");

            System.out.println(id);
            System.out.println(string);
            System.out.println(age);

            System.out.println("----------------");
        }

        // 释放资源
        resultSet.close();
        stmt.close();
        conn.close();
    }
}

我们再给出一个mysql和Java结合的常用案例:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import pojo.Student;

// JDBC_SQL案例演示
// 查询jdbc_test数据库,封装进Student对象,并存储到ArrayList集合中
public class Demo6 {

    public static void main(String[] arg) throws Exception{
        // 创建集合
        List<Student> list = new ArrayList<>();

        String url = "jdbc:mysql://127.0.0.1:3306/test?useSSL=false";
        String username = "root";
        String password = "123456";
        Connection conn = DriverManager.getConnection(url,username,password);

        // 先设置SQL语句
        String sql = "select * from jdbc_test";

        // 然后获得对象
        Statement stmt = conn.createStatement();

        // 然后开始执行语句
        ResultSet resultSet = stmt.executeQuery(sql);

        // 然后我们循环得到数据
        while (resultSet.next()){
            // 创建对象
            Student s = new Student();

            int id = resultSet.getInt("id");
            String string = resultSet.getString(2);
            int age = resultSet.getInt("age");

            // 赋值
            s.setId(id);
            s.setName(string);
            s.setAge(age);

            // 把对象插入集合
            list.add(s);
        }

        // 我们查看结果
        System.out.println(list);

        // 释放资源
        resultSet.close();
        stmt.close();
        conn.close();
    }
}

PreparedStatement

PreparedStatement的作用有两个:

  1. 预防SQL注入问题

首先我们先来介绍SQL注入问题:

我们给出一段Web端之前的账号登录匹配代码:

import com.itheima.pojo.Account;
import org.junit.Test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

/**
 * 用户登录
 */
public class JDBCDemo6_UserLogin {

    @Test
    public void testLogin() throws  Exception {
       //2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写
       String url = "jdbc:mysql:///db1?useSSL=false";
       String username = "root";
       String password = "1234";
       Connection conn = DriverManager.getConnection(url, username, password);

       // 接收用户输入 用户名和密码(这里直接写入,我们会在JavaWeb部分学到交互)
        String name = "zhangsan";
        String pwd = "fhsjkfhdsk";

        String sql = "select * from tb_user where username = '"+name+"' and password = '"+pwd+"'";

        // 获取stmt对象
        Statement stmt = conn.createStatement();

        // 执行sql
        ResultSet rs = stmt.executeQuery(sql);

        // 判断登录是否成功
        if(rs.next()){
            System.out.println("登录成功~");
        }else{
            System.out.println("登录失败~");
        }

        //7. 释放资源
        rs.close();
        stmt.close();
        conn.close();
    }
}

我们可以注意到上述的sql语句采用的是字符串拼接,

因而当我们采用一些特殊字符时,就会导致mysql的搜索语句变为true,搜索到所有的mysql内容然后进入第一个账号

import com.itheima.pojo.Account;
import org.junit.Test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

/**
* 用户登录
*/
public class JDBCDemo6_UserLogin {
    
	 /**
     * 演示SQL注入
     * @throws Exception
     */
    @Test
    public void testLogin_Inject() throws  Exception {
        //2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写
        String url = "jdbc:mysql:///db1?useSSL=false";
        String username = "root";
        String password = "1234";
        Connection conn = DriverManager.getConnection(url, username, password);

        // 接收用户输入 用户名和密码
        String name = "hfkjsfhskj";
        // 注意这里"' or '1' = '1"带入到sql语句中就会导致变为select * from tb_user where true
        String pwd = "' or '1' = '1";

        String sql = "select * from tb_user where username = '"+name+"' and password = '"+pwd+"'";
        System.out.println(sql);
        // 获取stmt对象
        Statement stmt = conn.createStatement();
        // 执行sql
        ResultSet rs = stmt.executeQuery(sql);

        // 判断登录是否成功
        if(rs.next()){
            System.out.println("登录成功~");
        }else{
            System.out.println("登录失败~");
        }

        //7. 释放资源
        rs.close();
        stmt.close();
        conn.close();
    }

因而我们采用PreparedStatement来预防SQL注入问题

我们先来介绍PreparedStatement的语法:

// 获得PreparedStatement对象

// 首先我们需要设置sql语句,并且将参数用?代替
String sql = "select * from table where usename = ? and password = ?";
    
// 我们在创建PreparedStatement对象时需要直接将sql语句带入
PreparedStatement pstmt = conn.PreparedStatement(sql);

// 然后我们需要设置参数值
pstmt.setXxx(参数1,参数2);

/*
Xxx: 数据类型,包括Int,Double,String等
参数1:?的位置编号,从1开始
参数2:?的值
*/

// 最后执行SQL
pstmt.executeQuery();

下面我们给出整体案例解释PreparedStatement操作:

import org.junit.Test;

import java.sql.*;
import java.util.Date;

/**
 * API详解:PreparedStatement
 */
public class JDBCDemo7_PreparedStatement {

    @Test
    public void testPreparedStatement() throws  Exception {
       //2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写
       String url = "jdbc:mysql:///db1?useSSL=false";
       String username = "root";
       String password = "1234";
       Connection conn = DriverManager.getConnection(url, username, password);

       // 接收用户输入 用户名和密码
        String name = "zhangsan";
        String pwd = "' or '1' = '1";

        // 定义sql
        String sql = "select * from tb_user where username = ? and password = ?";

        // 获取pstmt对象
        PreparedStatement pstmt = conn.prepareStatement(sql);

        // 设置?的值
        pstmt.setString(1,name);
        pstmt.setString(2,pwd);

        // 执行sql
        ResultSet rs = pstmt.executeQuery();

        // 判断登录是否成功
        if(rs.next()){
            System.out.println("登录成功~");
        }else{
            System.out.println("登录失败~");
        }

        //7. 释放资源
        rs.close();
        pstmt.close();
        conn.close();
    }
}

然后我们稍微拓展一下为什么PreparedStatement为什么不会导致字符串拼接错误:

  1. 预编译SQL,提高性能

PreparedStatement预编译原理:

数据库连接池

首先我们对数据库连接池做出简单介绍:

数据库连接池优点:

我们采用通俗解释来说:

我们的数据库会有很多人访问,每当来一个人操作数据库,MYSQL创建一个Connection,在这个人使用后,再将Connection删除,

这种资源重复创造删除,导致数据库效率低下

我们的数据库具有一定的Connection数量,当每来一个人,MYSQL分配给它一个Connection,并在使用后回收;

如果这个人的使用时间超过正常时间,MYSQL将会自动回收

数据库连接池实现

我们从三个方法讲解数据库连接池的实现:

Druid(德鲁伊)使用

Druid的使用分为五步:

我们给出实例代码:

# 定义配置文件

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///db1?useSSL=false&useServerPrepStmts=true
username=root
password=1234
# 初始化连接数量
initialSize=5
# 最大连接数
maxActive=10
# 最大等待时间
maxWait=3000
import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.FileInputStream;
import java.sql.Connection;
import java.util.Properties;

/**
 * Druid数据库连接池演示
 */
public class DruidDemo {

    public static void main(String[] args) throws Exception {
        //1.导入jar包(在网上可以找到,同JDBC包一样)
        
        //2.定义配置文件

        //3. 加载配置文件
        Properties prop = new Properties();
        prop.load(new FileInputStream("jdbc-demo/src/druid.properties"));
        //4. 获取连接池对象
        DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);

        //5. 获取数据库连接 Connection
        Connection connection = dataSource.getConnection();

        System.out.println(connection);


        //System.out.println(System.getProperty("user.dir"));
    }
}

结束语

好的,关于JDBC的内容我们就讲解到这里!

附录

该文章属于学习笔记,主要学习B站黑马JDBC视频

这里附上链接:黑马JDBC视频全套视频教程,快速入门jdbc原理+jdbc实战,一套掌握_哔哩哔哩_bilibili

标签:JDBC,Java,String,java,MYSQL,stmt,sql,import,conn
来源: https://www.cnblogs.com/qiuluoyuweiliang/p/16558827.html