浅析使用JDBC操作MySQL需要添加Class.forName("com.mysql.jdbc.Driver")

引言

如果熟悉使用JDBC来连接数据库的同学一定很清楚连接数据库的代码中一定会有依据Class.forName

("com.mysql.jdbc.Driver");
  public static Connection getConnection() throws ClassNotFoundException, SQLException {
    if(connection == null){
      Class.forName("com.mysql.jdbc.Driver");
      connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/xxx?serverTimezone=UTC", "root", "xxxxxx");
    }
    return connection;
  }

之前没有想过为什么需要有这么一个语句,都是按照文档直接这么做的,在这篇文章中我来试着解释这么做的原因。

类加载机制

在这之前我们先来说下Java中的类加载机制。

在Java中如果想要使用一个类,则必须要求该类已经被加载到Jvm中,加载的过程实际上就是通过类的全限定名来获取定义该类二进制字节流,然后将这个字节流所表示的静态存储结构转换为方法去的动态运行时数据结构。同时在在内存中实例化一个java.lang.Class对象,作为方法区中该类的数据访问入口(供我们使用)。

而会触发类加载的会有如下几种情况(引用自<<深入理解Java虚拟机>>):

1.遇到new、getstatic、putstatic或invokestatic这4条字节码指令时,如果类没有进行过初始化,则需要先触发其初始化。生成这4条指令的最常见的Java代码场景是:使用new关键字实例化对象的时候、读取或设置一个类的静态字段(被final修饰、已在编译期把结果放入常量池的静态字段除外)的时候,以及调用一个类的静态方法的时候。

2.使用java.lang.reflect包的方法对类进行反射调用的时候,如果类没有进行过初始化,则需要先触发其初始化。

3.当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化。

4.当虚拟机启动时,用户需要指定一个要执行的主类(包含main()方法的那个类),虚拟机会先初始化这个主类。

Class.forName

在Java官方文档中对Class.forName的解释为在运行时动态的加载一个类,返回值为生成的Class对象。

那么很明显在jdbc中使用Class.forName("com.mysql.jdbc.Driver");仅仅就是将com.mysql.jdbc.Driver类加载到Jvm中了,这个原因大多数人应该都知道。

但是我们要知道Class.forName貌似只是对类进行了加载,我们甚至都没有对返回的Class对象做任何操作,那么我们为什么后面就可以直接用了呢?

首先看Class.forName调用了native方法forName0(...);

@CallerSensitive
public static Class<?> forName(String className)
      throws ClassNotFoundException {
  Class<?> caller = Reflection.getCallerClass();
  return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
}

private static native Class<?> forName0(String name, boolean initialize,ClassLoader loader,Class<?> caller);

要注意forName0中有一个关键的参数boolean initialize,;该参数用来标识在将该类加载后是否进行初始化操作。可以看到代码中是true,就表示会进行初始化操作。

初始化过程实际上就是对变量赋值(不是赋初值,不会调用构造函数)的过程。包含所有类变量的赋值以及静态代码语句块的执行代码,包括对父类的初始化。

再看com.mysql.jdbc.Driver驱动类:

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!");
    }
  }
}

该类中定义了一个静态代码块,静态代码快中创建了一个驱动类实例注册给了DriverManager,而静态代码块的内容会在初始化的过程中执行,所以才能通过DriverManager.getConnection直接获取一个连接。

其他加载类方法

我们需要明白的是在Java中并不是只有通过Class.forName()才能显示的加载类。那么为什么不使用其他的加载方法而偏偏选择Class.forName()呢?

ClassLoader.getSystemClassLoader().loadClass()

通过类加载器也可以将一个类加载到Jvm中。通过ClassLoader.getSystemClassLoader().loadClass("com.mysql.jdbc.Driver");也可以加载驱动类。

但是如果我们深入看下loadClass的实现:

public Class<?> loadClass(String name) throws ClassNotFoundException {
  return loadClass(name, false);
}

protected Class<?> loadClass(String name, boolean resolve);

可以看到其调用了一个重载的方法,该方法也有一个boolean类型的变量boolean resolve,调用时默认为false。该参数用于标识是否对加载后的类进行链接操作,如果不进行连接操作则不会有初始化的操作。

所以如果使用这种加载类方式的话理论上来说是没发使用该驱动类的。

new关键字

也可以使用new关键字进行加载操作,在使用new关键字时会查看该类是否已经被加载,如果没有被加载的话则会进行加载操作。所以我们的类中也可以这样写:

public static Connection getConnection() throws ClassNotFoundException, SQLException {
  if(connection == null){
    new Driver();//会自动调用静态代码块
    connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/xxx?serverTimezone=UTC", "root", "xxxx");
  }
  return connection;
}

但是实际上因为在驱动类的静态代码快中实际上已经有了实例化对象并注册到DriverMananger中的操作。所以这里根本就没有在实例化一个对象的过程。使用Class.forName即可,这也算是一个优化的过程吧。

可以不使用Class.forName("com.mysql.jdbc.Driver")

在测试的过程中发现即使不显示的使用Class.forName("com.mysql.jdbc.Driver")也能够连接到数据库,一时间觉得很奇怪。

深入跟踪代码后发现实际上只要我们引入了mysql的驱动包,那么在使用时会根据驱动包下提供的配置文件默认的创建一个类。

所以实际上只要引入了该驱动包,那么使用jdbc是可以直接通过DriverManage来获取连接。

public static Connection getConnection() SQLException {
  return DriverManager.getConnection("jdbc:mysql://localhost:3306/xxx?serverTimezone=UTC", "root", "xxxxxx");
}

总结

以上所述是小编给大家介绍的为什么使用JDBC操作MySQL需要添加Class.forName("com.mysql.jdbc.Driver") ,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • mysql下载与安装过程详解

    1:下载MySql 官网下载地址:https://dev.mysql.com/downloads/mysql/ 选择对应的下载文件.(我电脑是64位,所以这下载的是64位的下载文件) 2:安装MySql 打开下载文件解压到指定文件目录.(我这里解压目录为D:\mysql-5.7.21-winx64) 打开解压后的MySql文件在根目录下创建my.ini (mysql配置文件) my.ini文件内容如下: (建议直接复制粘贴下面文件) 这里需要将basedir 与 datadir 路径改成mysq

  • MySQL数据库8——数据库中函数的应用详解

    数据库中内置函数的使用 该篇主要介绍数据库中内置函数的使用,主要有日期函数,字符串函数,数学函数. (一)日期函数 select current_date();//获得当前日期,年月日 select current_time();//获得当前时间,时分秒 select current_timestamp();//获得当前 年月日 时分秒 select date('2017-10-28');//获得参数日期 select date_add('2017-10-28', interval 10 day

  • MySQL数据库定时备份的实现方法

    1. 创建shell脚本 vim backupdb.sh 创建脚本内容如下: #!/bin/sh db_user="root" db_passwd="123456" db_name="userdb" name="$(date +"%Y%m%d%H%M%S")" /usr/bin/mysqldump -u$db_user -p$db_passwd $db_name >>/home/backup/$

  • MySQL执行状态的查看与分析

    当感觉mysql性能出现问题时,通常会先看下当前mysql的执行状态,使用 show processlist 来查看,例如: 其中state状态列信息非常重要,先看下各列含义,然后看下state常用状态 各列的含义 1.id 一个标识,你要kill一个语句的时候使用,例如 mysql> kill 207; 2.user 显示当前用户,如果不是root,这个命令就只显示你权限范围内的sql语句 3.host 显示这个语句是从哪个ip 的哪个端口上发出的,可用来追踪出问题语句的用户 4.db 显示这

  • php+mysql开发的最简单在线题库(在线做题系统)完整案例

    本文实例讲述了php+mysql开发的最简单在线题库.分享给大家供大家参考,具体如下: 题库,对于教育机构,学校,在线教育,是很有必要的,网上也有不少的第三方在线题库系统,但是本次案例,会让有需要的人了解题库的开发思路,其实很简单,无非就是一个表单验证,数据库验证. 1.先构建表单数据 2.把表单数据通过get或者post方式提交到表单验证页面,和数据库进行匹配 3.返回结果,答案正确或者错误 构建表单: index.php <!DOCTYPE html> <html> <h

  • 详解一条sql语句在mysql中是如何执行的

    概览 最近开始在学习mysql相关知识,自己根据学到的知识点,根据自己的理解整理分享出来,本篇文章会分析下一个sql语句在mysql中的执行流程,包括sql的查询在mysql内部会怎么流转,sql语句的更新是怎么完成的. 一.mysql架构分析 下面是mysql的一个简要架构图: mysql主要分为Server层和存储引擎层 Server层:主要包括连接器.查询缓存.分析器.优化器.执行器等,所有跨存储引擎的功能都在这一层实现,比如存储过程.触发器.视图,函数等,还有一个通用的日志模块 bing

  • MySQL使用LOAD_FILE()函数方法总结

    在MySQL中,LOAD_FILE()函数读取一个文件并将其内容作为字符串返回. 语法 LOAD_FILE(file_name) 其中file_name是文件的完整路径. 下面是我从一个文件中选择内容的示例: SELECT LOAD_FILE('/data/test.txt') AS Result; 结果: +------------------------------------------+ | Result | +--------------------------------------

  • mysql数据库和oracle数据库之间互相导入备份

    把从Oracle数据库导出的数据导入到MySql数据库中 1. 使用默认的结束符号导入到MySql数据库中: LOAD DATA LOCAL INFILE 'd:/oracle.txt' IGNORE INTO TABLE alarmLog 此时Fields的结束符默认的就是'/t'制表符,而不是"/t"字符串. 2. 当设定Fields结束符导入到MySql数据库中: LOAD DATA LOCAL INFILE 'd:/oraclea.txt' IGNORE INTO TABLE

  • mysql unique key在查询中的使用与相关问题

    1.建表语句: CREATE TABLE `employees` ( `emp_no` int(11) NOT NULL, `birth_date` date NOT NULL, `first_name` varchar(14) NOT NULL, `last_name` varchar(16) NOT NULL, `gender` char(1) NOT NULL, `hire_date` date NOT NULL, PRIMARY KEY (`emp_no`), UNIQUE KEY `i

  • mysql 8.0.15 下载安装详细教程 新手必备!

    本文记录了mysql 8.0.15 下载安装的具体步骤,供大家参考,具体内容如下 背景:作为一个热爱技术但不懂代码的产品写的教程 1.环境 系统:windows 64位 mysql版本:mysql 8.0.15 2.下载篇 首先是下载数据库安装文件,进入mysql官网下载频道https://www.mysql.com/downloads/,依次点击Community→MySQL Community Server,如下图: 进入下载页面后,选择操作系统,这里我们选择默认的Microsoft Win

随机推荐