JDBC-01

JDBC

前言

  在学习了SQL语句后,我们肯定会思考如何使用数据库里的数据。这个时候,我们便要学习JDBC来将数据库与JAVA结合在一块。

 

正题

什么是JDBC?

Java数据库连接,(Java Database Connectivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口。

 

JDBC的主要用途

  1. 与数据库建立连接
  2. 发送 SQL 语句
  3. 处理结果

 

数据库驱动

在学习JDBC之前,我们必须了解一个东西,驱动。

驱动:两个设备(两个应用)之间通信的桥梁。

 

JDBC的开发步骤

  1. 加载驱动
  2. 获取连接
  3. 基本操作(CRUD)
  4. 释放资源

 

使用JDBC的准备工作

  1.创建一个maven项目(当然你也可以不用这种方法,但maven在开发中最为方便)

  【创建方式请看我之前的博客:利用Maven进行导jar包】

  2.导入mysql的jar包

<dependencies>
       <dependency>
           <groupId>mysql</groupId>
           <artifactId>mysql-connector-java</artifactId>
           <version>5.1.6</version>
       </dependency>
 </dependencies>

  完成以上的操作,我们便可以开始进行JDBC的学习了。

 

JDBC的简单例子(先了解一下整体的框架,后面会相应的解释以及简化)

package com.jdbc.demo01;

import org.junit.Test;
import java.sql.*;

/**
 *

 * JDBC的入门程序

 * @author  Charles
   *
    */
   public class JDBCdemo1 {
    @Test
public void demo01() throws ClassNotFoundException, SQLException { // 1.加载驱动 Class.forName("com.jdbc.Driver"); // 2.获得连接 Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/web_test3", "root" , "1234"); // 3.基本操作:执行SQL // 3.1获得执行SQL语句的对象 Statement statement = conn.createStatement(); // 3.2编写SQL语句: String sql = "select * from user"; // 3.3执行SQL: ResultSet rs = statement.executeQuery(sql); // 3.4遍历结果集 while (rs.next()){ System.out.println(rs.getInt(("id")+ " ")); System.out.println(rs.getInt(("username")+ " ")); System.out.println(rs.getInt(("password")+ " ")); System.out.println(rs.getInt(("nickname")+ " ")); System.out.println(rs.getInt(("age"))); System.out.println(); } // 4.释放资源 rs.close(); statement.close(); conn.close(); } }

 

接下来我来介绍一下上面代码的含义:

DriverManager:驱动管理类

  作用:①注册驱动 ②获得连接

①:

// 1.加载驱动,双引号里面的内容一般是标准
Class.forName("com.jdbc.Driver");

 

此时,你或许会好奇,不是注册驱动吗,为什么代码是加载驱动。

首先,我们来看看JAVA的API中Driver注册驱动的介绍JDBC-01

 

 

这种方式的确可以完成驱动的注册,但是实际开发中并不会这么做。

原因:

  如果需要注册驱动,就会使用DirverManager.registerDriver(new Driver()); ,但是在查询源代码的时候,我们发现源代码中有一段静态代码块已经调用了注册驱动的方法。因此,如果我们再手动调用注册,就会导致驱动被注册两次。

JDBC-01

 

所以调用 Class.forName 将自动将加载驱动程序类。(具体的原理可以查看一些API文档)

 

②:Connection conn = DriverManager.getConnection(url, user, password);

// 2.获得连接
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/web_test3", "root", "1234");

 参数介绍:

  • url:与数据库连接的路径
  • user:与数据库连接的用户名
  • password:与数据库连接的密码

 

url:

"jdbc:mysql://localhost:3306/web_test3"
  • jdbc:连接数据库的协议
  • mysql:是jdbc的子协议
  • localhost:连接的Mysql数据库服务器的主机地址【本机:localhost,非本机:连接主机的IP地址】
  • 3306:Mysql数据库服务器的端口号
  • web_test3:数据库名称

 

Connection:与数据库的连接对象

  作用:①创建执行SQL语句的对象  ②管理事务

①:常用的三个对象:Statement、CallableStatement、PreparedStatement

Statement:执行SQL语句

JDBC-01

 

 

CallableStatement:执行数据库的存储过程

JDBC-01

 

PrepardedStatement:执行SQL语句,对SQL进行预处理。(用于解决SQL注入漏洞问题)

JDBC-01

 

②:三个常用对象:setAutoCommit、commit、rollback

setAutoCommit

JDBC-01

 

 

commit

JDBC-01

 

rollback

 JDBC-01

 

接下来我们来看看Statement的详细操作:

作用:①执行SQL  ②执行批处理

①:常用的执行SQL方法: 主要使用的是后两个

  • boolean execute(String sql)

  执行查询,修改,添加,删除的SQL语句

JDBC-01

 

  • ResultSet executeQuery(String sql) 

  执行查询(Select 语句)

JDBC-01

 

  • int executeUpdate(String sql)

  执行修改,添加,删除的SQL语句

JDBC-01

 

 

②:常用的执行批处理的方法

 addBatch

JDBC-01

 

clearBatch

JDBC-01

 

executeBatch

JDBC-01

 

ResultSet:结果集

通过select语句的查询结果

 

结果集的遍历:

JDBC-01

 

 

JDBC-01

 

结果集的获取:

JDBC-01

 

JDBC-01

结果集的获取可以使用: getxxx(); 通常都会有重载的方法。

getxxx(int columnIndex);

getxxx(String columnName);

 

JDBC的资源释放:

  JDBC程序执行结束后,将与数据库进行交互的对象释放掉,通常是ResultSet,Statement(PreparedStatement),Connection。

  这几个对象尤其是Connection对象是非常稀有的,这个对象一定要做到尽量晚创建,尽早释放掉。

  注:释放代码应写入finally的代码块中。

 

具体实现:

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

 

CRUD的操作:

保存操作:

package com.charles.sql;

import org.junit.*;

import java.sql.*;

public class Demo01 {
    @Test
    public void demo01(){
        Connection conn = null;
        Statement statement = null;
        try{
            // 注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            // 获得连接
            conn = DriverManager.getConnection("jdbc:mysql:///web_test3", "root",
                    "1234);
            // 执行操作
            // 创建执行SQL语句对象
            statement = conn.createStatement();
            // 编写SQL语句
            String sql = "insert into user values (null, ‘eee‘, ‘123‘, ‘Jack‘, 21)";
            // 执行SQL语句
            int num = statement.executeUpdate(sql);
            if (num > 0){
                System.out.println("保存用户成功!");
            }

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            // 释放资源
            if (statement != null){
               try{
                   statement.close();
               } catch (SQLException e){
                   e.printStackTrace();
               }
               statement = null;
            }

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

        }
    }

}

 

修改操作:

package com.charles.sql;

import org.junit.*;

import java.sql.*;

public class Demo01 {
    @Test
    public void demo01(){
        Connection conn = null;
        Statement statement = null;
        try{
            // 注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            // 获得连接
            conn = DriverManager.getConnection("jdbc:mysql:///web_test3", "root",
                    "1234");
            // 执行操作
            // 创建执行SQL语句对象
            statement = conn.createStatement();
            // 编写SQL语句
            String sql = "update user set password=‘2222‘,nickname=‘biubiu‘ where id=6";
            // 执行SQL语句
            int num = statement.executeUpdate(sql);
            if (num > 0){
                System.out.println("修改用户成功!");
            }

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            // 释放资源
            if (statement != null){
               try{
                   statement.close();
               } catch (SQLException e){
                   e.printStackTrace();
               }
               statement = null;
            }

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

        }
    }

}

 

删除操作:

package com.charles.sql;

import org.junit.*;

import java.sql.*;

public class Demo01 {
    @Test
    public void demo01(){
        Connection conn = null;
        Statement statement = null;
        try{
            // 注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            // 获得连接
            conn = DriverManager.getConnection("jdbc:mysql:///web_test3", "root",
                    "1234");
            // 执行操作
            // 创建执行SQL语句对象
            statement = conn.createStatement();
            // 编写SQL语句
            String sql = "delete from user where id=6";
            // 执行SQL语句
            int num = statement.executeUpdate(sql);
            if (num > 0){
                System.out.println("删除用户成功!");
            }

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            // 释放资源
            if (statement != null){
               try{
                   statement.close();
               } catch (SQLException e){
                   e.printStackTrace();
               }
               statement = null;
            }

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

        }
    }

}

 

查询操作:

①多条信息查询:

package com.charles.sql;

import org.junit.*;

import java.sql.*;

public class Demo01 {
    @Test
    public void demo01(){
        Connection conn = null;
        Statement statement = null;
        ResultSet rs = null;
        try{
            // 注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            // 获得连接
            conn = DriverManager.getConnection("jdbc:mysql:///web_test3", "root",
                    "1234");
            // 执行操作
            // 创建执行SQL语句对象
            statement = conn.createStatement();
            // 编写SQL语句
            String sql = "select * from user";
            // 执行SQL语句
            rs = statement.executeQuery(sql);
            while(rs.next()){
                 System.out.println(rs.getInt(("id")+ " "));
                System.out.println(rs.getInt(("username")+ " "));
                System.out.println(rs.getInt(("password")+ " "));
                System.out.println(rs.getInt(("nickname")+ " "));
                System.out.println(rs.getInt(("age")));
                System.out.println();
            }

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            // 释放资源
            if (statement != null){
               try{
                   statement.close();
               } catch (SQLException e){
                   e.printStackTrace();
               }
               statement = null;
            }

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

        }
    }

}

 

②一条信息查询:

package com.charles.sql;

import org.junit.*;

import java.sql.*;

public class Demo01 {
    @Test
    public void demo01(){
        Connection conn = null;
        Statement statement = null;
        ResultSet rs = null;
        try{
            // 注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            // 获得连接
            conn = DriverManager.getConnection("jdbc:mysql:///web_test3", "root",
                    "1234");
            // 执行操作
            // 创建执行SQL语句对象
            statement = conn.createStatement();
            // 编写SQL语句
            String sql = "select * from user where id=1";
            // 执行SQL语句
            rs = statement.executeQuery(sql);
            if(rs.next()){
                System.out.println(rs.getInt("id")+" "+rs.getString("username")+" 
                                   "+re.getString("password"));
            }

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            // 释放资源
            if (statement != null){
               try{
                   statement.close();
               } catch (SQLException e){
                   e.printStackTrace();
               }
               statement = null;
            }

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

        }
    }

}

 

JDBC工具类的抽取:

目的:包装成工具类后,能够更方便地使用JDBC,减少不必要的工作量

package org.charl;

import java.sql.*;

/**
 * JDBC工具类
 * @author Charles
 */

public class Demo {

    // 默认设置
    public static final String driverClassName;
    public static final String url;
    public static final String username;
    public static final String password;
    static {
        driverClassName = "com.mysql.jdbc.Driver";
        url = "jdbc:mysql:///web_test3";
        username = "root";
        password = "1234";
    }
    // 注册驱动类
    public static void loadDriver(){
        try {
            Class.forName(driverClassName);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    // 获得连接
    public static Connection getConnection(){
        Connection conn = null;
        try {
            loadDriver();
            conn = DriverManager.getConnection(url,username,password);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return conn;
    }

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

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

    public static void release(Statement st,Connection conn, ResultSet rs){
        if (st != null){
            try{
                st.close();
            } catch (SQLException e){
                e.printStackTrace();
            }
            st = null;
        }

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

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

 

配置文件:

  创建一个:db.properties配置文件

  作用:用来存储数据库用户等信息

  目的:简化工具类的代码

演示:

JDBC-01

 

 

在工具类中解析属性文件

JDBC-01

 

JDBC的SQL注入漏洞:

  什么是SQL注入漏洞?

    假设有一个网站,用户需要进行注入。用户注册后根据用户名和密码进行登录。假设该用户的用户名被其他人知道了,但他并不     知道密码,也可以登录到网站上进行相应的用户操作。

 

  漏洞分析:

JDBC-01

 

 

  SQL注入漏洞的解决方法

  采用PreparedStatement对象解决SQL注入漏洞问题。该对象将SQL预先进行编译,使用‘?‘作为占用符。‘?‘所代表的内容是SQL所固定。如果再次传入变量(包括SQL的关键字),这个时候也不会识别这些关键字。

 

PreparedStatement预编译:

具体操作:

package com.charles.sql;

import java.sql.*;

/***
 * @return
 * @author Charles
 */

public class Demo02 {
    public boolean login(String username, String password){

        Connection conn = null;
        PreparedStatement preparedStatement = null;
        ResultSet rs = null;
        boolean flag = false;
        try{
            conn = org.charl.Demo.getConnection();
            String sql = "select * from user where username = ? and password = ?";
            preparedStatement = conn.prepareStatement(sql);
            // 设置参数
            preparedStatement.setString(1,username);
            preparedStatement.setString(2,password);
            rs = preparedStatement.executeQuery();
            if (rs.next()){
                flag = true;
            }
        } catch (SQLException e){
            e.printStackTrace();
        } finally {
            org.charl.Demo.release(preparedStatement,conn,rs);
        }
        return flag;
    }
}

 

JDBC批处理操作:

  什么是批处理?

    批处理就是将所有SQL语句一起执行。

常用的方法已在前面介绍过。

注意:通常情况下MySQL批处理是没有开启的,要想执行批处理,就要在url的内容中进行相应的添加。

?rewriteBatchedStatements=true

JDBC-01

 

 

接下来展示一下比较完整的实例:

【里面包含了PreparedStatement等内容,之前的案例看不懂没关系,这个案例供大家参考】

 

数据库web_test4中user表原先的信息

JDBC-01

 

 

工具类代码

package org.charl;

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

/**
 * JDBC工具类
 * @author Charles
 */

public class Demo {

    // 默认设置
    public static final String driverClassName;
    public static final String url;
    public static final String username;
    public static final String password;
    static {
        driverClassName = "com.mysql.jdbc.Driver";
        url = "jdbc:mysql:///web_test4?rewriteBatchedStatements=true?characterEncoding=utf-8";
        username = "root";
        password = "1234";
    }
    // 注册驱动类
    public static void loadDriver(){
        try {
            Class.forName(driverClassName);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    // 获得连接
    public static Connection getConnection(){
        Connection conn = null;
        try {
            loadDriver();
            conn = DriverManager.getConnection(url,username,password);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return conn;
    }

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

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

    public static void release(Statement st,Connection conn, ResultSet rs){
        if (st != null){
            try{
                st.close();
            } catch (SQLException e){
                e.printStackTrace();
            }
            st = null;
        }

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

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

 

执行主代码

package com.charles.sql;

import org.junit.Test;

import java.sql.*;

public class Demo03 {
    @Test
    public void Test(){
        long begin = System.currentTimeMillis();
        Connection conn = null;
        PreparedStatement preparedStatement = null;
        ResultSet rs = null;
        try{
            // 注册驱动 + 获得连接
            conn = org.charl.Demo.getConnection();
            // 编写SQL语句
            String sql = "insert into user values(null,?)";
            // 预编译
            preparedStatement = conn.prepareStatement(sql);
            for (int i =1;i<10000;i++){
                preparedStatement.setString(1,"name"+i);
                // 添加到批处理
                preparedStatement.addBatch();
                // 执行批处理
                if (i % 1000 == 0){
                    preparedStatement.executeBatch();
                    // 进行清空防止数据溢出
                    preparedStatement.clearBatch();
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            // 释放资源
            org.charl.Demo.release(preparedStatement,conn,rs);
        }
        long end = System.currentTimeMillis();
        System.out.println("耗时:"+ (end - begin) + "ms");
    }
}

 

执行成功后:

控制台

JDBC-01

 

 

此时user表中的数据

JDBC-01

 

 

小结

  以上就是JDBC入门的介绍,当然在刚学习JDBC的时候,肯定会出现许多错误,这些错误或许一时间会让你抓狂,但请耐心地解决,相信后面收获肯定满满的。

                                加油!

                          时间:2020-04-02 20:57:18

JDBC-01

上一篇:Extjs fieldText内容


下一篇:MySQL慢日志中COMMIT事件