浅析使用JDBC操作MySQL需要添加Class.forName("com.mysql.jdbc.Driver")
作者:宁愿呢 发布时间:2024-01-21 23:08:48
引言
如果熟悉使用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") 网站的支持!
来源:https://www.cnblogs.com/liyus/p/10634554.html
猜你喜欢
- 代码如下:CREATE FUNCTION dbo.f_splitstr( @str varchar(8000) )RETURNS
- 之前也写过这个小组件,最近遇到select下加搜索的功能,所以稍微完善一下。效果图:子组件 dropdown.vue<template
- 情景是这样的:在C#中调用python脚本进行post请求,python脚本中使用了requests包。Python的开发环境我们有比较多的
- 1 Python自动绘图在这里我主要运用了pyautocad库进行AutoCAD的自动化操作,pyautocad是一款功能非常强大的Auto
- 本文实例为大家分享了python opencv实现图像矫正的具体代码,供大家参考,具体内容如下问题简介一般的我们对图像中的目标进行分析和检测
- 一、下载SQL Server 2008 R2安装文件cn_sql_server_2008_r2_enterprise_x86_x64_ia6
- 本文实例讲述了Python基础之字符串常见操作。分享给大家供大家参考,具体如下:字符串基本操作切片# str[beg:end]# (下标从
- 有时候,我们需要在字符串中加入相应的变量,以下提供了几种字符串加入变量的方法:1、+ 连字符name = 'zhangsan'
- 本文进通过实例,讲述通过 prototype 自定义方法的过程,旨在抛砖引玉,如果不对的地方,欢迎指正!prototype 是在 IE 4
- 如何制作一个小巧的购物车?主程序如下:cartkit.aspClass CartKitSub CreateCart()&
- 《hadoop权威指南》的天气数据可以在ftp://ftp3.ncdc.noaa.gov/pub/data/noaa下载,在网上看到这个数据
- 首先先安装好我们的Python 这里就不多介绍了1.打开python.exe:点击File 下的小扳手图标 Settings…2.打开设置界
- 目录一、比较汽车性能二、比较不同城市近期天气状况雷达图是以从同一点开始的轴上表示的三个或更多个定量变量的二维图表的形式显示多变量数据的图形方
- 先看下效果图:用到的模块:PyMySQLrequeststhreadingwxpy要实现上面的示例,首先是有两大块地方获取天气信息通过微信将
- 前言今天我们简单说下Python函数和控制语句,大纲如下:函数“脏活累活交给函数来做”,首先,看看P
- 最近做项目中有一个模块是用于实时监控的,左边有个菜单栏用于显示所有的设备,那当然是从数据库中动态获取的了,右边是个iframe用于显示监控画
- 完整的示例代码如下: 代码如下:<%@LANGUAGE="JAVASCRIPT" CODEPAGE="6
- mysqldump工具备份备份整个数据库$> mysqldump -u root -h host -p dbname > bac
- 开发目的这算是node应用的第二个小应用吧,主要目的是熟悉node和express框架。原理很简单:在node搭建的环境下引用第三方包处理图
- 笔者今天就谈谈自己对这两种操作模式的理解,并且给出一些可行的建议,跟大家一起来提高Oracle数据库的安全性。 一、非归档模式的利与弊。 非