JDBC连接——原生连接(mysql)(创建工具类的方式加载驱动)

 

准备工作:JDK1.9,idea 2017,jdbc架包mysql-connector-java-5.1.18-bin.jar

写作目的:之前写JDBC连接,一直都是按照老师给的模板,一步一步的写,没有想过为什么,而通过工作后对编程理解的加深和对源码的挖掘,理解了每一步为什么这样写。在此将自己的理解做以梳理和总结,以供日后学习。

 

目录

JDBC连接介绍

JDBC的四个核心类

数据库表:

建表

插入数据

六步jdbc连接分析

加载驱动

2、获取连接

3、获取执行sql语句对象

4、执行sql语句

5、获取结果

6、关闭资源

JDBC连接代码实现

总结:


JDBC连接介绍

JDBC(Java DataBase Conectivity ) java数据库连接,善良的Sun公司为了解决不同的数据库连接而制定的一种规范(或者说是一些接口和类)。不同的数据库实现java的连接就要实现这些接口(或继承这些类)。这里的mysql-connector-java-5.1.18-bin.jar就是mysql实现jdbc的类jar包。Java提供访问数据库规范称为JDBC,而生产厂商(如mysql、Oracle)提供规范的实现类称为驱动。

JDBC的四个核心类

DriverManager:用于加载驱动

Connection:用户获取连接

Statement:用于操作数据库sql语句

ResultSet:结果集

数据库表:

建表

 

CREATE TABLE `book` (
  `bookid` int(11) NOT NULL AUTO_INCREMENT,
  `bookname` varchar(50) DEFAULT NULL,
  `rmb` float(7,2) DEFAULT NULL,
  `FRO` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`bookid`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8

插入数据

 

六步jdbc连接分析

1、加载驱动

市面是加载驱动的方法是通过加载jar包下com.mysql.jdbc.Driver的字节码文件实现的,我们来探究下为什么要这样写!

实际上加载驱动用到的是DriverManager下的静态方法registerDriver(java.sql.Driver driver) 

源码如下(1-1):

 public static void registerDriver(java.sql.Driver driver)
        throws SQLException {

        registerDriver(driver, null);
    }

这是sun公司提供的规范,传的参数driver是相应的sql驱动

而mysql的jdbc连接jar包内相应的注册驱动的源码是(1-2)

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.mysql.jdbc;

import java.sql.DriverManager;
import java.sql.SQLException;

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    public Driver() throws SQLException {
    }

    static {
        try {
            DriverManager.registerDriver(new Driver());
        } catch (SQLException var1) {
            throw new RuntimeException("Can't register driver!");
        }
    }
}

将1-2以对象形式作为参数传入1-1中

即(1-3)

 DriverManager.registerDriver(new com.mysql.jdbc.Driver())

如此即完成了数据库的加载,但是观察1-1和1-2的代码可知1-1本身即是加载数据库驱动,但是1-2作为被传入的参数对象,在被编译后,会加载内部的静态代码块!静态代码块中的DriverManager.registerDriver(new Driver())也加载了数据库驱动!所以,这里等于加载了两次驱动!为了使驱动只被加载一次!此处可以通过仅new mysql jar包中的Driver对象,加载里面的静态方法来实现数据库的加载!

即(1-4)

new com.mysql.jdbc.Driver()

其实用这样的方式加载驱动对于一个初入java坑的新手来说是最好理解,也足够实现功能的一个方式!但是java开发追求的是高可用性!通过new驱动的方式加载驱动,显得不够灵活!而通过加载字节码文件的方式加载com.mysql.jdbc.Driver类来编译运行内部的静态代码块执行DriverManager.registerDriver(new Driver()) 将驱动变成参数,这样的话,当使用不同的数据库时只需要改变(1-5)

Class.forName("com.mysql.jdbc.Driver")

内部的参数即可,大大提高的了代码的灵活性。

其实jdbc驱动设计的初期已经将代码的灵活性考虑在内!所以将注册驱动的方法设计在了静态代码块中!

2、获取连接

DriverManager下的静态方法getConnection() 源码如图(1-6)

DriverManager.getConnection(url,user,password)

 public static Connection getConnection(String url,
        String user, String password) throws SQLException {
        java.util.Properties info = new java.util.Properties();

        if (user != null) {
            info.put("user", user);
        }
        if (password != null) {
            info.put("password", password);
        }

        return (getConnection(url, info, Reflection.getCallerClass()));
    }

这里可以很清楚的看到user信息和password信息被传进了Properties集合,这个集合也是java预留的唯一的一个可以加载流文件的集合

3、获取执行sql语句对象

Connection 的createStatement()方法或者 prepareStatement(String sql)

createStatement()处理的sql不能有参数也就是?号,返回Statement

prepareStatement可以用来处理有参数的sql语句,返回PrepareStatement,效率要比createStatment高,所以一般都用prepareStatement。

prepareStatement给参数赋值的方法时setObject(int index,Objectparament) 使用Object的好处是可以忽略数据库和java之间数据类型的转化!

4、执行sql语句

调用executeQuery()方法和executeUpdate方法 createStatement在此传入sql语句

executeQuery()只执行查询语句(DQL),executeUpdate()只执行增删改语句(DML)

5、获取结果

执行完sql语句后返回的是一个ResultSet集合,里面的next用来指向下一行

获取每行元素需要调用getInt(int index)、getString(int index)\getDouble(int index)等方法依次获取对应的值,这里不建议用getObject(int index)的方法获取值,因为往往需要获取每个值后,需要对其进行操作,如果获取的是Object类型的数据,则在使用的时候需要向下转型。

6、关闭资源

所有和外部资源相关的资源都需要关!

连接(Connection),sql对象(Statement/PrepareStatement),结果集(ResultSet)


JDBC连接代码实现

以上是对JDBC六步的分析。简单的JDBC从加载驱动、获取连接,到获取执行sql的对象、执行sql,再到处理结果集、关闭资源实际上就是一个系统实现被用户使用,获取数据的一个完整的过程。用户使用系统,就是频繁的进行数据的增删改查,而频繁的增删改查过程中,数据库似乎只需要被加载一次!这样加载驱动这一步就可以单独写在一个类的静态代码块中,在类被加载时,执行静态代码块进而加载驱动,类只会被加载一次!而类只要被加载,就会执行静态代码块!数据库驱动就会被加载!

这个放加载驱动代码块的类,可以是一个工具类!工具类里面处理定义加载驱动的静态代码块,还可以定义获取连接的静态方法,在其他类调用此工具类的获取连接方法时,如果类没被加载,则加载类,如果已经被加载,那就直接获取连接。此外这个类还可以定义关闭资源的方法,在使用完连接后关闭相应资源。分析至此一个高复用性的工具类就诞生了,里面包含的是加载驱动的静态代码块,获取连接的静态方法,以及关闭资源的静态方法。代码如下(2-1)

package test01;

import java.sql.*;

/**
 * @Author: ${user}
 */
public class JdbcPlus {
/*私有化构造函数,这是定义工具类的固有格式,想java源码中的Colletions、Arrays等都是工具类,都私有化了构造函数*/
private JdbcPlus(){}

    //1、私有化的静态成员变量,在静态代码块中实现赋值
    private static String url;
    private static String user;
    private static String password;

    static {
        try {
            //2、加载驱动,同时赋值
            url = "jdbc:mysql://localhost:3306/school";
            user = "root";
            password = "1234";
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    //获取连接,参数已经在静态代码块中被初始化,返回类型为Connection
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url, user, password);
    }

    //关闭资源,此处为了提高效率,加了非空判断,如果是空,代表没获取到,则不需要关
    public static void close(Connection conn, Statement stat, ResultSet rs) {
        try {
            if (conn != null)
                conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        try {
            if (stat != null)
                stat.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        try {
            if (rs != null)
                rs.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }

    }

}

一个高可用的工具类就完成了。在实际开发中只需要调用JdbcPlus.getConnection()即可实现加载驱动获取连接的功能,而数据库驱动也只加载一次,我们再定义一个Test_jsp类(2-2)来完成接下来的步骤:

package test01;

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

/**
 * @Author: ${user}
 */
public class Test_jsp {

    public static void main(String[] args) throws SQLException {
        //加载获取连接
        Connection conn = JdbcPlus.getConnection();
        String str = "select * from book";
        //获取执行sql的对象
        PreparedStatement ps = conn.prepareStatement(str);
        //执行查询功能
        ResultSet rs = ps.executeQuery();
        //处理结果集
        while(rs.next()){
            System.out.print(rs.getInt(1));
            System.out.print(rs.getString(2));
            System.out.print(rs.getDouble(3));
            System.out.println(rs.getString(4));
        }
        //关闭资源
        JdbcPlus.close(conn,ps,rs);
    
    }
}

总结:

脑子里面觉得代码实现其实也就那回事,但是真正把它具体的描述出来发现总是词穷,羞于表达!学习的路程还漫长!诸位看客觉得有哪些地方在下没表达清楚的欢迎指出,也欢迎诸位沟通赐教!

能力尚浅,有待进步,如有不足,不吝赐教! 


后面是配置文件方式进行JDBC连接的详细步骤及源码,特意来附上连接,方便跳转

配置文件写JDBC连接

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值