JDBC(Java操作MySQL数据库学习记)

JDBC学习记

入门案例:

package com.summarize.jdbc;
/*
我们操作数据库的步骤:
    1、建立连接
    2、执行SQL语句
    3、获取返回结果
    4、退出(exit,关闭连接,释放资源)

Java程序操作数据库的过程:
    1、注册驱动
    2、建立连接
    3、获取SQL执行平台
    4、执行SQL语句
    5、处理结果集
    6、退出(关闭连接,释放资源)

 */

// 以下程序测试Java程序是如何连接MySQL并执行SQL语句的

import org.junit.Test;

import java.sql.*;
import java.util.Properties;

public class FooDemo {

    @Test
    public void testJDBC() throws SQLException {
        // 注册驱动
        Driver driver = new com.mysql.jdbc.Driver();

        // 建立连接
        String url = "jdbc:mysql://localhost:3306/jdbc_db?useSSL=false";
        Properties info = new Properties();
        info.setProperty("user", "root");
        info.setProperty("password", "123456");
        Connection conn = driver.connect(url, info);


        // 获取SQL执行平台
        Statement stmt = conn.createStatement();


        // 执行SQL语句
        String sql = "select * from user";
        ResultSet res = stmt.executeQuery(sql);
        
        
        // 处理结果集
        while (res.next()) {
            int id  = res.getInt(1);
            String name = res.getString(2);
            int age = res.getInt(3);
            String balance = res.getString(4);

            System.out.println(id + " " + name + " " + age + " " + balance);
        }
        
        // 释放资源
        res.close();
        stmt.close();
        conn.close();


    }

}

1、Driver和DriverManager

package com.summarize.driver;

import org.junit.Assert;
import org.junit.Test;

import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;

/*
    Driver
        Connection connect(String url, Properties info)
        info;至少应该包括"user" 和 "password"属性。

   DriverManager:
        static void registerDriver(Driver driver)
        static void deregisterDriver(Driver driver)
        static Connection getConnection(String url, String user, String password)


 */

public class DriverDemo {

    // 版本一:通过 Driver获取连接
    @Test
    public void testDriver1() throws SQLException {
        String url = "jdbc:mysql://localhost:3306/jdbc_db?useSSL=false";
        Properties info = new Properties();
        info.setProperty("user", "root");
        info.setProperty("password", "123456");
		
        Driver driver = new com.mysql.jdbc.Driver();

        Connection conn = driver.connect(url, info);

        Assert.assertNotNull(conn);
    }

    // 版本二:通过DriverManager链接
    @Test
    public void testDriver2() throws Exception {

        // 读取配置文件
        Properties info = new Properties();
        try(Reader reader = new FileReader("jdbc.properties")) {
            info.load(reader);
        } catch (IOException e) {
            e.printStackTrace();
        }

        String driverClass = info.getProperty("driverClass");
        String url = info.getProperty("url");
        String uer = info.getProperty("username");
        String password = info.getProperty("password");

        // 注册驱动
        Class<?> driverType = Class.forName(driverClass);
        Driver driver = (Driver) driverType.newInstance();
        DriverManager.registerDriver(driver);

        // 获取连接
        Connection conn = DriverManager.getConnection(url, uer, password);
        Assert.assertNotNull(conn);

    }
    

    //版本三:通过DriverManager链接

    @Test
    public void testDriver3() throws SQLException {

        // 读取配置文件
        Properties info = new Properties();
        try(Reader reader = new FileReader("jdbc.properties")) {
            info.load(reader);
        } catch (IOException e) {
            e.printStackTrace();
        }

        String url = info.getProperty("url");
        String uer = info.getProperty("username");
        String password = info.getProperty("password");

        // 获取连接
        Connection conn = DriverManager.getConnection(url, uer, password);
        Assert.assertNotNull(conn);

    }
}

// 配置文件:jdbc.properties

driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbc_db?useSSL=false
username=root
password=123456

2、Statement

我们可以通过 Statement 执行各种 SQL 语句,包括 DDL、DCL、DML、DQL等。
通过 Statement 创建数据库、创建表、插入数据、更新数据、查找数据、删除表、删除数据库

package com.summarize.statement;

import org.junit.Assert;
import org.junit.Test;

import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.sql.*;
import java.util.Properties;

/*
Statement:
    boolean execute(String sql): 可以执行任何SQL语句, 如果有结果集返回true, 否则返回false.
    int executeUpdate(String) 可以执行DDL和DML, 返回受影响的行数
    ResultSet executeQuery(String sql) 执行DQL,返回结果集。不管有没有满足查询条件的记录,ResultSet都不为null.
        我们可以通过ResultSet的next()方法判断是否有满足查询条件的记录。
 */

public class StatementDemo {

    //创建连接(连接mysql数据库)
    private Connection getConnection() throws Exception {
        // 通过DriverManager获取连接
        Properties info = new Properties();

        try(Reader reader = new FileReader("jdbc.properties")) {
            info.load(reader);
        } catch (IOException e) {
            e.printStackTrace();
        }

        String driverClass = info.getProperty("driverClass");
        String url = info.getProperty("url");
        String uer = info.getProperty("user");
        String password = info.getProperty("password");

        // 注册驱动
        Class<?> driverType = Class.forName(driverClass);
        Driver driver = (Driver) driverType.newInstance();
        DriverManager.registerDriver (driver);

        // 获取连接
        return DriverManager.getConnection(url,uer,password);
    }


    // 通过 Statement 创建数据库、创建表、插入数据、更新数据、查找数据、删除表、删除数据库
    
    // 创建数据库
    @Test
    public void createDatabase() throws Exception {
        // 获取连接
        Connection conn = getConnection();
        Statement stmt = conn.createStatement();

        // 创建数据库cba
        String sql = "create database if not exists `cba`";
        boolean b = stmt.execute(sql);
        Assert.assertFalse(b);
    }

    // 创建表
    @Test
    public void createTable() throws Exception {
        // 获取连接
        Connection conn = getConnection();
        Statement stmt = conn.createStatement();

        // 创建在数据库cba中创建一个球员表player,包含字段id、name、height、position
        String sql1 = "use cba";
        String sql2 = "create table if not exists player(id int primary key, name varchar(20), height float, position varchar(20));";
        boolean b1 = stmt.execute(sql1);
        boolean b2 = stmt.execute(sql2);
        Assert.assertFalse(b1);
        Assert.assertFalse(b2);
    }

    // 插入数据
    @Test
    public void insertValues() throws Exception {
        // 获取数据库连接
        Connection conn = getConnection();
        // 向user表中插入6条数据
        String sql = "insert into user values (null, '王梦薇', 25, 2000000),(null, '马建旭', 25, 2000000)," +
                                             "(null, '杨广硕', 25, 2000000),(null, '张玮轩', 25, 2000000)," +
                                             "(null, '戴俊杰', 25, 2000000),(null, '李灿鹏', 25, 2000000);";

        Statement stmts = conn.createStatement();

        boolean b = stmts.execute(sql);
        stmts.executeQuery(sql);
        // int rows = stmts.executeUpdate(sql); 返回受影响的行数
        Assert.assertFalse(b);
    }

    // 更新数据
    @Test
    public void testUpdate() throws Exception {
        Connection conn = getConnection();
        Statement stmt = conn.createStatement();
        String sql = "update user set balance='5000000' where id=8";
        int rows = stmt.executeUpdate(sql);
        Assert.assertEquals(1, rows);
    }

    // 查询数据
    @Test
    public void testQuery() throws Exception {
        Connection conn = getConnection();
        Statement stmt = conn.createStatement();
        String sql = "select * from user where id=10";
        ResultSet rs = stmt.executeQuery(sql);
        Assert.assertTrue(rs.next());
    }

    
}


//jdbc.properties
driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbc_db?useSSL=false&useServerPrepStmts=true&cachePrepStmts=true
user=root
password=123456
  • Statement会引入SQL注入问题

3、PreparedStatement

通常我们只需一条SQL语句要经过下面三个过程。

  1. 解析器解析(SQL语法是否正确,词法是否正确)
  2. 优化器优化(判断是否使用索引,制定执行计划)
  3. 执行器执行并返回结果集

我们把这种普通的SQL语句称为Immediate Statements。

但是很多情况下,一条SQL语句可能被反复的执行。或者反复执行的SQL语句,他们的结构相似,只是参数不同而已。如果每次执行的时候都要经过上面的词法语义解析、优化SQL、制定执行计划等,那效率就明显不行了。

MySQL提供了预编译语句,可以帮我们解决这个问题。在预编译语句中,我们占位符?代替参数,这样我们只需改变参数就可以执行多条SQL语句,提供统一的模板。我们把这种SQL语句称为PreparedStatements。

预编译语句的优势有以下两点:

  1. 一次解析优化,多次执行
  2. 可以防止SQL注入问题

语法:

# 编译
prepare stmt_name from prepare_stmt;

# 执行
execute stmt_name [using @var_name [, @var_name] ...];

# 删除
{deallocate | drop} prepare stmt_name

我们需要开启服务端预编译,在 url 后面添加一些参数。
url=jdbc:mysql://localhost:3306/jdbc_db?
useServerPrepStmts=true&cachePrepStmts=true 
useServerPrepStmts: 是否启用服务端预编译, true表示启用。
cachePrepStmts:是否缓存预编译语句, true表示缓存。

4、Batch批处理

不管是 Statement 还是 PreparedStatement,执行一条 SQL 语句,客户端都要和服务器进行一次通信,这样效率就比较低下。因此,MySQL 提供了批处理功能。

默认情况下,MySQL 没有开启批处理模式。需要在 url 后面添加 rewriteBatchedStatements=true 参数。

代码演示:

package DbUtils;

/*
需要的jar包:
    1、mysql驱动jar包
    2、单元测试jar包(junit4)

Java操作数据库的步骤:
    1、注册驱动
    2、建立连接
    3、获取SQL执行平台
    4、执行SQL语句
    5、获取结果集
    6、退出(关闭连接、释放资源)
 */


import org.junit.Assert;
import org.junit.Test;

import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.sql.*;
import java.util.Properties;

/*
    Statement:
        void addBatch(String sql)
        void clearBatch()
        int[] executeBatch()
 */

public class BatchDemo {

    // 获取连接
    private Connection getConnection() throws ClassNotFoundException, IllegalAccessException, InstantiationException, SQLException {
        // 1、读取配置文件
        Properties info = new Properties();
        try(Reader reader = new FileReader("jdbc.properties")) {
            info.load(reader);
        } catch (IOException e) {
            e.printStackTrace();
        }
        String driverClass = info.getProperty("driverClass");
        String url = info.getProperty("url");
        String user = info.getProperty("user");
        String password = info.getProperty("password");

        // 2、获取注册驱动
        // 通过反射获取驱动类型,并创建改类型对象
        Class<?> driverType = Class.forName(driverClass);
        Driver driver = (Driver) driverType.newInstance();
        // 注册驱动
        DriverManager.registerDriver(driver);

        // 3、建立连接
        return DriverManager.getConnection(url, user, password);

    }


    // 批处理
    @Test
    public void testPerformance() throws Exception {
        Connection conn = getConnection();

        String sql = "insert into t_user (name, age, balance) values (?,?,?)";
        PreparedStatement pstmt = conn.prepareStatement(sql);
        long start = System.currentTimeMillis();
        for (int i = 0; i < 10000; i++) {
            if (i % 1000 == 0) {
                pstmt.executeBatch();    // 执行
                pstmt.clearBatch(); // 清空
            }
            pstmt.setString(1, "张三" + i);
            pstmt.setString(2, "1" + i);
            pstmt.setString(3, "1000000" + i);

            // 添加到Batch
            pstmt.addBatch();
        }
        long end = System.currentTimeMillis();
        System.out.println(end - start + "ms");
    }

}
    
# 配置文件jdbc.properties
driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbc_db?useSSL=false&useServerPrepStmts=true&rewriteBatchedStatements=true
user=root
password=123456

5、ResultSet

Java 中用 ResultSet 接口代表数据库返回的结果集。
ResultSet 封装执行结果时,采用的类似于表格的方式。ResultSet 对象维护了一个指向表格数据行的游标,初始的时候,游标在第一行之前。ResultSet 的 next() 方法,可以判断是否有还有下一行数据。如果有,返回 true, 将游标指向该行,我们可以通过 ResultSet 对象获取该行的数据。如果没有,返回
false。

常用API

getXXX(int index)

getXXX(String columnName)

next()
previous()
absolute(int row)

beforeFirst()
afterLast()

代码实现:

package DbUtils;

import org.junit.Test;

import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.sql.*;
import java.util.Properties;

public class ResultSet {
    // 获取连接
    public Connection getConnection() throws Exception {
        // 读取配置文件
        Properties info = new Properties();
        try(Reader reader = new FileReader("jdbc.properties")) {
            info.load(reader);
        } catch (IOException e) {
            e.printStackTrace();
        }

        String driverClass = info.getProperty("driverClass");
        String url = info.getProperty("url");
        String user = info.getProperty("user");
        String password = info.getProperty("password");
        // 获取驱动类型并通过该类型的Class对象创建驱动
        Class<?> driverType = Class.forName(driverClass);
        Driver driver = (Driver) driverType.newInstance();

        // 注册驱动
        DriverManager.registerDriver(driver);

        // 获取连接
        return DriverManager.getConnection(url, user, password);

    }

    // ResultSet测试
    /*
        常用API测试:
            getXXX(int index) getXXX(String columnName) next()
            previous()
            absolute(int row) beforeFirst()
            afterLast()
     */
    @Test
    public void testResultSet() throws Exception {
        // 获取连接
        Connection conn = getConnection();

        String sql = "select * from user";
        PreparedStatement pstmt = conn.prepareStatement(sql);
        java.sql.ResultSet res = pstmt.executeQuery();

        // 处理结果集
        System.out.println("正向遍历:");
        while (res.next()) {
            int id = res.getInt(1);
            String name = res.getString(2);
            String  age = res.getString(3);
            String balance = res.getString(4);
            System.out.println(id + " " +  name + " " + age + "" + balance);
        }

        System.out.println("\n 逆向遍历:");
        while (res.previous()) {
            String name = res.getString("name");
            String balance = res.getString("balance");
            int id = res.getInt("id");
            int age = res.getInt("age" );

            System.out.println(id + " " + name + " " + age + " " + balance);
        }
        res.close();
        conn.close();

    }

}
# 配置文件同上

后续内容在下一篇博客更新!

你可能感兴趣的:(MySQL,Java)