如果使用JDBC来操作MySQL数据库

Posted IT_Holmes

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如果使用JDBC来操作MySQL数据库相关的知识,希望对你有一定的参考价值。

本章是关于JDBC 的相关内容,模拟JDBC操作数据库。源码和jar包获取:https://gitee.com/it-sherlock/jdbc-source-code

1. 数据库驱动

一般分是三个部分,先是,调用JDBC这一部分;然后调用JDBC驱动;最后,访问数据库。

2. JDBC

SUN公司为了简化,开发人员的(对数据库的统一)操作,提供了一个(Java操作数据库)

这些规范的实现由具体的厂商去做。

对于开发人员来说,我们只需要掌握JDBC的操作就可以了。

JDBC驱动下载:https://mvnrepository.com/artifact/mysql/mysql-connector-java

3. 第一个 JDBC 程序

创建测试的数据库:

CREATE DATABASE jdbcStudy CHARACTER SET utf8 COLLATE utf8_general_ci;

USE jdbcStudy

CREATE TABLE users(
	id INT PRIMARY KEY,
	`name` VARCHAR(40),
	`password` VARCHAR(40),
	email VARCHAR(60),
	birthday DATE
);

INSERT INTO users (id,`name`,`password`,email,birthday) 
VALUES (1,'zhangsan','123456','zs@qq.com','1999-11-01'),(2,'lisi','123456','ls@qq.com','1229-11-01'),(3,'wangwu','123456','ww@qq.com','2009-11-01');

1. 创建一个项目。

2. 导入数据库驱动jar包。

3. 编写测试代码。

package com.zhangsan.demo01;

import java.sql.*;

// 我的第一个jdbc程序
public class JdbcFistDemo {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        // 1. 加载驱动
        Class.forName("com.mysql.jdbc.Driver"); // 固定写法,加载驱动

        // 2. 用户信息和url
        // 三个参数:useUnicode=true&characterEncoding=utf8&useSSL=true
        // useUnicode=true :支持中文编码
        // characterEncoding=utf8 :设置字符集为utf8
        // useSSL=true :使用安全的连接
        String url = "jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true";
        String username = "root";
        String password = "123456";

        // 3. 连接成功,数据库对象 这里的connection代表数据库
        Connection connection = DriverManager.getConnection(url,username,password);

        // 4. 执行sql的对象 Statement用来执行sql的
        Statement statement = connection.createStatement();
        // 5. 执行sql
        String sql = "SELECT * FROM users";
        // resultSet :返回的结果集,结果集中封装了我们全部的查询结果
        ResultSet resultSet = statement.executeQuery(sql);

        while (resultSet.next()){
            System.out.println("id = " + resultSet.getObject("id"));
            System.out.println("name = " + resultSet.getObject("name"));
            System.out.println("pwd = " + resultSet.getObject("password"));
            System.out.println("email = " + resultSet.getObject("email"));
            System.out.println("birthday = " + resultSet.getObject("birthday"));
            System.out.println("===============================================");
        }
        // 6. 释放连接(关闭连接)
        // 关闭连接的顺序刚好是反着的
        resultSet.close();
        statement.close();
        connection.close();
    }
}

步骤总结:

  • 1.加载驱动,Class.forName(“com.mysql.jdbc.Driver”);
  • 2.连接数据库 DriverManager
  • 3.获得执行sql的对象 Statement
  • 4.获得返回的结果集 ResultSet
  • 5.释放连接(关闭连接)

DriverManager:

// DriverManager.registerDriver(new com.mysql.jdbc.Driver());
Class.forName("com.mysql.jdbc.Driver"); // 固定写法,加载驱动
//其实上面的forName就是调用的DiverManager中的registerDriver,使用上推荐使用forName。
//它们两个功能都是一样的,加载驱动



// connection 代表的就是数据库。
Connection connection = DriverManager.getConnection(url,username,password);

// 前面在mysql中所说的事务回滚,事务提交,数据库设置为自动提交,都可以通过connection来操作。
connection.rollback();
connection.commit();
connection.setAutoCommit();

URL:

// 三个参数:useUnicode=true&characterEncoding=utf8&useSSL=true
// useUnicode=true :支持中文编码
// characterEncoding=utf8 :设置字符集为utf8
// useSSL=true :使用安全的连接
String url = "jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true";

//mysql 默认端口号:3306
//mysql的URL格式:
//jdbc:mysql://主机地址:端口号/数据库名?参数1&参数2&参数3

//oracle 默认端口号:1521
//oracle的URL格式:
//jdbc:oracle:thin:@localhost:1521:sid

//像jdbc:mysql 或者 jdbc.oracle 这些都是一种协议。

Statement执行SQL对象:(还有一个PrepareStatement 也是执行sql对象的)

String sql = "SELECT * FROM users"; // 编写sql

statement.executeQuery("sql语句"); //查询操作,返回resultSet。
statement.execute("sql语句"); //可以执行任何sql,它能执行任何sql就说明它会有一个判断形式,性能比其他语句低。
statement.executeUpdate("sql语句"); // 更新,插入,删除,都是用update操作。
statement.executeBatch("sql语句"); //可以存放多个sql语句,执行。

ResultSet 查询的结果集:封装了所有的查询结果

ResultSet resultSet = statement.executeQuery(sql);


resultSet.getObject("列名"); //在不知道列类型的情况下使用,getObject()

//如果知道列的类型就是用指定类型
resultSet.getString("列名");
resultSet.getInt("列名");
resultSet.getFloat("列名");
resultSet.getDate("列名");
...

ResultSet结果集的遍历,指针操作:

resultSet.beforeFirst(); // 移动到最前面
resultSet.afterLast(); // 移动到最后面
resultSet.next();  // 移动到下一个数据
resultSet.previous(); //移动到前一行
resultSet.absolute(row); //移动到指定行

释放资源:

resultSet.close();
statement.close();
connection.close(); 
// 一定要释放资源,用完关掉!不然占内存。

4. statement 对象

JDBC中的statement对象用于向数据库发送SQL语句,向完成对数据库的增删改查,只需要通过这个对象向数据库发送增删改查语句即可。

  • statement对象中的executeUpdate方法,用于向数据库发送增删改查的sql语句,它返回的是一个整数(即增删改语句导致了数据库几行数据发生了变化)。
  • statement.executeQuery方法用于像数据库发送查询语句,它返回一个ResultSet对象数据集。




封装数据:

db.properties 文件:用来存储连接数据库的内容。

// db.properties文件:
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true
username=root
password=123456

JdbcUtiles文件:获取db.properties文件内容,驱动加载,获取连接和释放连接操作。

// JdbcUtils文件:

package com.zhangsan.demo02.utils;

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

public class JdbcUtils {

    private static String driver = null;
    private static String url = null;
    private static String username = null;
    private static String password = null;

    static {
        try {
            //获取db.properties的文件,因为在src下,因此不用链接地址。 这里会返回一个输入流
            InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");

            Properties properties = new Properties();
            properties.load(in); // 读取字节流种的属性列表

            driver = properties.getProperty("driver");
            url = properties.getProperty("url");
            username = properties.getProperty("username");
            password = properties.getProperty("password");


            //1. 驱动加载
            Class.forName(driver);



        }catch (Exception e){
            e.printStackTrace();
        }
    }

    // 获取连接
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url,username,password);
    }

    //释放连接资源
    public static void release(Connection con, Statement st, ResultSet rs){
        if (rs!=null){
            try{
                rs.close();
            } catch (SQLException e){
                e.printStackTrace();
            }
        }

        if (st!=null){
            try{
                st.close();
            } catch (SQLException e){
                e.printStackTrace();
            }
        }

        if (con!=null){
            try{
                con.close();
            } catch (SQLException e){
                e.printStackTrace();
            }
        }
    }

}

操作sql语句的文件:增删改查。

//步骤都是一样,就是通过修改sql语句实现。注意是select查询语句有resultset返回集。

package com.zhangsan.demo02;

import com.zhangsan.demo02.utils.JdbcUtils;

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

public class TestUpdate {
    public static void main(String[] args) {

        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection(); // 获取数据库连接
            st = conn.createStatement(); //获得sql的执行对象
            String sql = "UPDATE users SET `name`='张三',`email`='无' WHERE id=3";

            int i = st.executeUpdate(sql);
            if (i>0){
                System.out.println("更新成功|!!");
            }
        } catch(SQLException e){
            e.printStackTrace();
        } finally {
            JdbcUtils.release(conn,st,rs);
        }
    }
}

SQL注入的问题:

sql存在漏洞,会被攻击导致数据泄露,换句话说就是将SQL语句进行拼接。

package com.zhangsan.demo02;

import com.zhangsan.demo02.utils.JdbcUtils;

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

public class SQL注入 {
    public static void main(String[] args) {
        //这样我们可以通过login链接数据库完成登录
        //login("张三","123456");

        //sql注入别的语句操作,这里通过拼接其他的sql语句即便没有密码用户,照样能获取数据库信息。
        login("' or '1=1","' or '1=1");

    }

    // 登录业务
    public static void login(String username,String password){
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection(); // 获取数据库连接
            st = conn.createStatement(); //获得sql的执行对象
            String sql = "SELECT * FROM users WHERE `name` = '"+username+"' AND `password` = '"+password+"'";

            rs = st.executeQuery(sql);

            while (rs.next()){
                System.out.println(rs.getString("name"));
                System.out.println(rs.getString("password"));
                System.out.println("===================================");
            }
        } catch(SQLException e){
            e.printStackTrace();
        } finally {
            JdbcUtils.release(conn,st,rs);
        }
    }
}

5. PreparedStatement 对象

PreparedStatement 可以防止SQL注入,并且效率更高。

PreparedStatement是继承了Statement这个类。

依照上面sql注入,采用preparedstatement就可以有效的避免:

package com.zhangsan.demo02;

import com.zhangsan.demo02.utils.JdbcUtils;

import java.sql.*;

public class SQL注入 {
    public static void main(String[] args) {
        //这样我们可以通过使用PreparedStatement就避免了SQL注入的问题。
        //login("老铁","123456");
        login("' or '1=1","' or '1=1");

    }

    // 登录业务
    public static void login(String username,String password){
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection();

            String sql = "SELECT * FROM users WHERE `name` = ? AND `password` = ?";

            // PreparedStatement 防止SQL注入的本质,把传递进来的参数当作字符。
            // 假设其中存在转移字符,比如说: ' 会被直接转义。
            st = conn.prepareStatement(sql);
            st.setString(1,username);
            st.setString(2,password);

            rs = st.executeQuery();

            while (rs.next()){
                System.out.println(rs.getString("name"));
                System.out.println(rs.getString("password"));
                System.out.println("===================================");
            }
        } catch(SQLException e){
            e.printStackTrace();
        } finally {
            JdbcUtils.release(conn,st,rs);
        }
    }
}

以上是关于如果使用JDBC来操作MySQL数据库的主要内容,如果未能解决你的问题,请参考以下文章

[MySQL]如何使用JDBC编程?

关于mysql驱动版本报错解决,Cause: com.mysql.jdbc.exceptions.jdbc4Unknown system variable ‘query_cache_size(代码片段

如何在片段中填充列表视图?

mysql jdbc源码分析片段 和 Tomcat's JDBC Pool

JDBC 控制事务(MySQL为例)

MySQL -----> JDBC编程