JAVA连接数据库是其众多功能中的一部分,主要有两种方式连接DataBase: 一种是采用JDBC-ODBC桥,另一种则是称之为纯驱动连接DataBase,第一种方式在大型项目中基本上不再使用,本系列文章主要分析纯驱动源码。

对于初学JAVA者,甚至那些使用JAVA做过几年开发的程序员来讲,对于JDBC的工作原理都不一定能够明白。知其然,不知其所以然。遇到问题就不知所 措了。通过针对于MYSQL JDBC源码的分析,对于JAVA是如何连接数据库,其中到底做了些什么工作,一步步解剖开来,更好的理解JDBC。

使用JAVA连接数据库,首先要做的就是在程序中导入sql包,然后装载驱动类、获取连接、获取语句对象、发送SQL命令然后得到结果

请看以下代码片段:

package javaT.sql;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.sql.Statement;

public class MysqlDemo {

public static void main(String[] args) throws Exception {

Connection conn = null;

String sql;

// MySQL的JDBC URL编写方式:jdbc:mysql://主机名称:连接端口/数据库的名称?参数=值

// 避免中文乱码要指定useUnicode和characterEncoding

// 执行数据库操作之前要在数据库管理系统上创建一个数据库,名字自己定,

// 下面语句之前就要先创建javademo数据库

String url = "jdbc:mysql://192.168.1.111:3306/appcenter_new?useUnicode=true&characterEncoding=utf8";

try {

// 之所以要使用下面这条语句,是因为要使用MySQL的驱动,所以我们要把它驱动起来,

// 可以通过Class.forName把它加载进去,也可以通过初始化来驱动起来,下面三种形式都可以

Class.forName("com.mysql.jdbc.Driver");// 动态加载mysql驱动

// or:

// com.mysql.jdbc.Driver driver = new com.mysql.jdbc.Driver();

// or:

// new com.mysql.jdbc.Driver();

System.out.println("成功加载MySQL驱动程序");

// 一个Connection代表一个数据库连接

conn = DriverManager.getConnection(url,"jbjava","jb98");

// Statement里面带有很多方法,比如executeUpdate可以实现插入,更新和删除等

Statement stmt = conn.createStatement();

sql = "create table student(NO char(20),name varchar(20),primary key(NO))";

int result = stmt.executeUpdate(sql);// executeUpdate语句会返回一个受影响的行数,如果返回-1就没有成功

if (result != -1) {

System.out.println("创建数据表成功");

sql = "insert into student(NO,name) values('2012001','陶伟基')";

result = stmt.executeUpdate(sql);

sql = "insert into student(NO,name) values('2012002','周小俊')";

result = stmt.executeUpdate(sql);

sql = "select * from student";

ResultSet rs = stmt.executeQuery(sql);// executeQuery会返回结果的集合,否则返回空值

System.out.println("学号\t姓名");

while (rs.next()) {

System.out

.println(rs.getString(1) + "\t" + rs.getString(2));// 入如果返回的是int类型可以用getInt()

}

}

} catch (SQLException e) {

System.out.println("MySQL操作错误");

e.printStackTrace();

} catch (Exception e) {

e.printStackTrace();

} finally {

conn.close();

}

}

}

/* 连接mysql 时装载的驱动类以及连接字符串 */

Class.forName(“com.mysql.jdbc.Driver”);//1

DriverManager.getConnection(“jdbc:mysql://localhost:3306/test”,”root”,”123”);//2

/* 连接SQLServer2005 时装载的驱动类以及连接字符串 */

Class.forName(“com.microsoft.sqlserver.jdbc.SQLServerDriver”);

DriverManager.getConnection(“jdbc:sqlserver://localhost:1433;databaseName=pubs”,”sa”, ””);

此段代码有两部分,连接不同数据库时所需要装载的驱动类以及连接字符串,以此获取连接。

Class.forName()装载类,在调用一个类的构造方法,初始化静态成员或者这个类有main方法时,JVM都会装载对应的类。

首先我们就看看com.mysql.jdbc.Driver类做了什么事情,找到MYSQL-JDBC驱动源码,解压之后找到src目录,然后找到com.mysql.jdbc下的Driver.java类

package com.mysql.jdbc;

import java.sql.SQLException;

public class Driver extends NonRegisteringDriver implements java.sql.Driver {

static {

try {

java.sql.DriverManager.registerDriver(new Driver()); //1

} catch (SQLException E) {

throw new RuntimeException("Can't register driver!");

}

}

// ~ Constructors

// -----------------------------------------------------------

/**

* Construct a new driver and register it with DriverManager

*

* @throws SQLException

* if a database error occurs.

*/

public Driver() throws SQLException {

// Required for Class.forName().newInstance()

}

}

Driver类继承NonRegisteringDriver 同时实现接口java.sql.Driver

此类会有一个静态块

static {

try {

java.sql.DriverManager.registerDriver(new Driver()); //1

} catch (SQLException E) {

throw new RuntimeException("Can't register driver!");

}

}

Class.forName的作用是要求JVM查找并加载指定的类, 也就是说JVM装载此类并执行静态块代码

此静态块只有一句关键部分,1处

在JDBC规范中明确要求这个Driver类必须向DriverManager注册自己,即任何一个JDBC 驱动

的Driver类的代码都必须类似下面这段

java.sql.DriverManager.registerDriver(new Driver());

所以,如果你要自己实现一个数据库的JDBC驱动,那么就得实现java.sql.Driver接口,并且需要在实现类中使用 java.sql.DriverManager.registerDriver(new Driver())注册自己,new Driver()就是创建一个Driver对象,所以此类会有一个无参数的构造函数:

public Driver() throws SQLException {

}

下面再看看DriverManager.registerDriver()这个方法,源码如下:

public static synchronized void registerDriver(java.sql.Driver driver)

throws SQLException {

if (!initialized) {

initialize();

}

DriverInfo di = new DriverInfo();

di.driver = driver;

di.driverClass = driver.getClass();

di.driverClassName = di.driverClass.getName();

// Not Required -- drivers.addElement(di);

writeDrivers.addElement(di);

println("registerDriver: " + di);

/* update the read copy of drivers vector */

readDrivers = (java.util.Vector) writeDrivers.clone();

}

此方法是一个静态同步的方法,形式参数是java.sql.Driver接口类型,因为com.mysql.jdbc.Driver这个类实现了 java.sql.Driver接口,所以com.mysql.jdbc.Driver实例对象new Driver()是可以作为实参传入到此方法中来的。在DriverManager类中都是使用的Driver接口类型,也就是说驱动的使用不依赖于任何 实现。如果需要更换你所连接的数据库,只需要在Class.forName传入的参数换成另一个数据库的驱动类,但要求此类必须实现Driver接口。

上一篇中分析了Class.forName(“com.mysql.jdbc.Driver”)幕后所做的事情,也就是在Driver实现类中的静 态块和构造函数,本篇主要来分析一下静态块的一句代码:DriverManager.registerDriver方法和其它相关的调用。

registerDriver方法是一个静态方法,它所要做的工作就是加载所有系统提供的驱动,并把它们添加到具体的类中,形成对象。同时还创建连接,是一个管理驱动的工具类。如果我们使用的是mysql,那么加载的也就是它的驱动。

此方法的源码如下:

public static synchronized void registerDriver(java.sql.Driver driver)

throws SQLException {

if (!initialized) { //1

initialize();

}

DriverInfo di = new DriverInfo();

di.driver = driver;

di.driverClass = driver.getClass();

di.driverClassName = di.driverClass.getName();

// Not Required -- drivers.addElement(di);

writeDrivers.addElement(di);

println("registerDriver: " + di);

/* update the read copy of drivers vector */

readDrivers = (java.util.Vector) writeDrivers.clone();

}

一、初始化操作

1、看看1处的代码,判断是否初始化,这个判断的变量是一个静态全局boolean值,初始为false

private static boolean initialized = false;

如果此变量的值为false那么它将会进入初始化方法,源码如下:

static void initialize() {

if (initialized) {

return;

}

initialized = true;

loadInitialDrivers();

println("JDBC DriverManager initialized");

}

2、Initialize方法中判断initialized值是否为真(其实就是通过此boolean变量判断是否已经初始化完成),之后设置 initialized值为true,接着又会调用另一个方法loadInitialDrivers() 同样是静态方法,用于调用系统类装载器,装载所有系统提供的驱动:

loadInitialDrivers()源码:

private static void loadInitialDrivers() {

String drivers;

try {

drivers = (String) java.security.AccessController.doPrivileged(

new sun.security.action.GetPropertyAction("jdbc.drivers"));

} catch (Exception ex) {

drivers = null;

}

// If the driver is packaged as a Service Provider,

// load it.

// Get all the drivers through the classloader

// exposed as a java.sql.Driver.class service.

DriverService ds = new DriverService();

// Have all the privileges to get all the

// implementation of java.sql.Driver

java.security.AccessController.doPrivileged(ds);

println("DriverManager.initialize: jdbc.drivers = " + drivers);

if (drivers == null) {

return;

}

while (drivers.length() != 0) {

int x = drivers.indexOf(':');

String driver;

if (x < 0) {

driver = drivers;

drivers = "";

} else {

driver = drivers.substring(0, x);

drivers = drivers.substring(x+1);

}

if (driver.length() == 0) {

continue;

}

try {

println("DriverManager.Initialize: loading " + driver);

Class.forName(driver, true,

ClassLoader.getSystemClassLoader());

} catch (Exception ex) {

println("DriverManager.Initialize: load failed: " + ex);

}

}

}

主要代码分析:

下面这段创建了一个内部类对象,创建此对象时,它会从系统服务中加载驱动

DriverService ds = new DriverService();

DriverService内部类的具体代码:

class DriverService implements java.security.PrivilegedAction {

Iterator ps = null;

public DriverService() {};

public Object run() {

ps = Service.providers(java.sql.Driver.class); //从系统服务中加载驱动

try {

while (ps.hasNext()) { //遍历驱动

ps.next();

} // end while

} catch(Throwable t) {

// Do nothing

}

return null;

} //end run

} //end DriverService

此句代码就是找到所有的拥有权限的java.sql.Driver的实现

java.security.AccessController.doPrivileged(ds);

下面这段,意思是得到系统属性jdbc.drivers对应驱动的驱动名称,使用了JAVA的安全许可

drivers = (String) java.security.AccessController.doPrivileged(

new sun.security.action.GetPropertyAction("jdbc.drivers"));

再看看后面的判断和循环

首先判断驱动服务对象是否为null,如果为null则返回,否则进入while循环,这个循环会依次遍历多个数据库驱动,因为jdbc:drivers 会有多个数据库驱动,驱动名是以:分割,接下来就是通过Class.forName依次装载驱动类,在其中使用了 ClassLoader.getSystemClassLoader()系统类装载器。

if (drivers == null) {

return;

}

while (drivers.length() != 0) {

Class.forName(driver, true, ClassLoader.getSystemClassLoader());

}

上面分析的就是在registerDriver方法中所要做的第一件事情:初始化。可以看到initialize()做的工作就是装载驱动,同时还 需要使用到系统的一些功能。如: java.security.AccessController.doPrivileged,此方法允许在一个类实例中的代码通知这个 AccessController,它的代码主体享受特权(Privileged),它不管这个请求是由什么代码所引发的,只是单独负责对它可得到的资源 的访问请求。比如说,一个调用者在调用doPrivileged方法时,可被标识为特权。AccessController做访问控制决策时,如果 checkPermission方法遇到一个通过doPrivileged方法调用而被视为特权调用者,那么checkPermission方法不会作许 可检查,表示那个访问请求是被允许的,如果调用者没有许可,则会抛出一个异常。

如:ClassLoader.getSystemClassLoader(),java中所有类都是通过ClassLoader装载的,ClassLoader可以为java程序提供很好的动态特性,有必要去深入理解哦。

接下来再看初始化之后的代码:

DriverInfo di = new DriverInfo();

di.driver = driver;

di.driverClass = driver.getClass();

di.driverClassName = di.driverClass.getName();

// Not Required -- drivers.addElement(di);

writeDrivers.addElement(di);

println("registerDriver: " + di);

/* update the read copy of drivers vector */

readDrivers = (java.util.Vector) writeDrivers.clone();

创建DriverInfo对象

DriverInfo di = new DriverInfo();

DriverInfo驱动信息类,是一个内部类,

源码如下:

class DriverInfo {

Driver driver;

Class driverClass;

String driverClassName;

public String toString() {

return ("driver[className=" + driverClassName + "," + driver + "]");

}

}

此类就是添加了三个属性,分别表示驱动对象,驱动的Class对象,以及驱动的类名;同时重写了toString方法。此内部类的作用就是以可以创建DriverInfo对象,以对象的形式保存驱动信息。

接下来就是设置对象的三个属性:

DriverInfo di = new DriverInfo();

di.driver = driver;

di.driverClass = driver.getClass();

di.driverClassName = di.driverClass.getName();

然后添加到集合writeDrivers中,这个集合是Vector类型,定义为DriverManager的属性

writeDrivers定义:

private static java.util.Vector writeDrivers = new java.util.Vector();

驱动添加到集合

writeDrivers.addElement(di);

最后就是调用writeDrivers对象的clone方法

readDrivers = (java.util.Vector) writeDrivers.clone();

readDrivers也是一个类型为Vector的集合,定义为DriverManager的属性

private static java.util.Vector readDrivers = new java.util.Vector();

为什么要先添加到writeDrivers然后再 clone到readDrivers中呢?

writeDrivers和 readDrivers两个都是驱动集合,无论是注册驱动抑或是取消注册,都是先对writeDrivers驱动集合中的数据进行添加或删除,然后再把 writeDrivers中的驱动都clone到readDrivers中,每次取出Driver并不是在writeDrivers中,而是在 readDrivers中取得。那么这两个驱动集合便可以这样理解,writeDrivers驱动集合负责注册驱动和注销驱动,readDrivers驱 动集合负责提供可用的驱动对象,readDrivers中的驱动对象应该都是可用的。把二者分开,使用者就不需加任何判断,很方便。

这里又涉及到一个知识就是clone, 有兴趣的朋友可以查看相关JAVA文档,Thinking in java 中也有详细描述。

这就是初始化的全过程,写了这么多,实际上只做一件事情,就是完成所有驱动的加载。装载之后就是连接了,在连载三当中我会详细描述。

第二篇中讲解了如何装载驱动,以及它的初始化过程。

本篇分析一下连接数据库时使用的获取数据库连接的代码:

DriverManager.getConnection(“jdbc:mysql://localhost:3306/test”,”root”,”123”);

DriverManager.getConnection方法有三种重载方式,这里我们使用带有三个参数的方法,第一个表示数据库的URL, 第二、三个分别

是用户名和密码。获取数据库连接如此简单,只要把三个参数准确无误的写上去,连接肯定就能获取。但是连接方法中到底给我们做

了哪些工作呢? 下面找到DriverManager类的静态方法getConnection源码一探究竟。

public static Connection getConnection(String url,

String user, String password) throws SQLException {

java.util.Properties info = new java.util.Properties(); ///1

// Gets the classloader of the code that called this method, may

// be null.

ClassLoader callerCL = DriverManager.getCallerClassLoader(); ///2

if (user != null) {

info.put("user", user);

}

if (password != null) {

info.put("password", password);

}

return (getConnection(url, info, callerCL)); ///3

}

1处定义了一个Properties对象,java.util.Properties它是用来在文件中存储键值对的,其中键和值是用等号分隔的。可以将值以

key-value的形式存入Properties.

2处调用方法getCallerClassLoader得到类装载器对象, 这个地方有点意思,既然是调用方法,怎么变成了下面这种形式呢?根本就

不见方法体。

源码:

private static native ClassLoader getCallerClassLoader();

getCallerClassLoader()是一个静态原生方法,返回类型为ClassLoader, 被声明为native, 说明这个方法是一个原生方法,也就是说

这个方法是用C/C++语言实现的,并且被编译成了DLL,由JAVA调用。这些函数的实体在DLL中,JDK源码并不包含,在JAVA源文件中是

找不到源代码的。不同的平台其实现也有所差异。这也是JAVA的底层机制,实际上JAVA就是在不同的平台上调用不同的native方法实

现对操作系统的访问。native关键字一般是和C/C++联合开发的时候使用。如果标明为native 要求运行时通知操作系统,这个函数必

须给我实现,JAVA需要调用。如果未实现,那么调用时会抛出一个异常java.lang.UnsatisfiedLinkError

接下来判断用户名和密码,并将其存放到Properties对象中:

if (user != null) {

info.put("user", user);

}

if (password != null) {

info.put("password", password);

}

调用获取连接的另一个重载方法

getCollection(String url, java.util.Properties info, ClassLoader callerCL)

return (getConnection(url, info, callerCL));

getConnection(url, info, callerCL) 源码:

private static Connection getConnection(

String url, java.util.Properties info, ClassLoader callerCL) throws SQLException {

java.util.Vector drivers = null;

synchronized(DriverManager.class) {

// synchronize loading of the correct classloader.

if(callerCL == null) {

callerCL = Thread.currentThread().getContextClassLoader();

}

}

if(url == null) {

throw new SQLException("The url cannot be null", "08001");

}

println("DriverManager.getConnection(/"" + url + "/")");

if (!initialized) {

initialize();

}

synchronized (DriverManager.class){

// use the readcopy of drivers

drivers = readDrivers;

}

// Walk through the loaded drivers attempting to make a connection.

// Remember the first exception that gets raised so we can reraise it.

SQLException reason = null;

for (int i = 0; i < drivers.size(); i++) {

DriverInfo di = (DriverInfo)drivers.elementAt(i);

// If the caller does not have permission to load the driver then

// skip it.

if ( getCallerClass(callerCL, di.driverClassName ) != di.driverClass ) {

println(" skipping: " + di);

continue;

}

try {

println(" trying " + di);

Connection result = di.driver.connect(url, info);

if (result != null) {

// Success!

println("getConnection returning " + di);

return (result);

}

} catch (SQLException ex) {

if (reason == null) {

reason = ex;

}

}

}

// if we got here nobody could connect.

if (reason != null) {

println("getConnection failed: " + reason);

throw reason;

}

println("getConnection: no suitable driver found for "+ url);

throw new SQLException("No suitable driver found for "+ url, "08001");

}

此方法代码较多,我们一步步来分析。

1、    传参

从前面的那个getConnection方法中形成的三个参数传递到这个getConnection方法中, 参数包括连接数据库的URL,包装了用户名和

密码的对象info, 通过调用原生函数返回的类装载器callerCL

2、    同步DriverManager.class

同步DriverManager的Class对象,synchronized同步的对象为DriverManager.class,是为同步正确的类加载器来加载类,在同步块

中判断传入的类装载器对象是否存在,如果为null, 通过当前线程来获取上下文类装载器,保证JDBC驱动程序类以外的rt.jar中的类

可以在这里被加载。有关于Thread和synchronized读者可以参考java多线程编程

synchronized(DriverManager.class) {

if(callerCL == null) {

callerCL = Thread.currentThread().getContextClassLoader();

}

}

3、    判断URL,如果为null则抛出SQLException异常

判断initialized的值,如果未初始化,继续调用初始化方法,此处在第二篇中已详细解释初始化过程,初始化之后writeDrivers 和readDrivers 将会有系统所有驱动数据,接下来使用synchronized同步DriverManager.class对象, 将方法中定义的集合drivers 引用 readDrivers对象,readDrivers是从writeDrivers拷贝过来

if(url == null) {

throw new SQLException("The url cannot be null", "08001");

}

println("DriverManager.getConnection(/"" + url + "/")");

if (!initialized) {

initialize();

}

synchronized (DriverManager.class) {

// use the readcopy of drivers

drivers = readDrivers;

}

4、    遍历驱动

通过for循环,遍历drivers集合,其中每个元素的类型为DriverInfo, 这个在第二篇中也有详细描述

首先取得集合中的每一个对象元素,调用getCallerClass()方法

for (int i = 0; i < drivers.size(); i++) {

DriverInfo di = (DriverInfo)drivers.elementAt(i);

if ( getCallerClass(callerCL, di.driverClassName ) != di.driverClass ) {

println(" skipping: " + di);

continue;

}

……

}

getCallerClass方法源码:

private static Class getCallerClass(ClassLoader callerClassLoader,

String driverClassName) {

Class callerC = null;

try {

callerC = Class.forName(driverClassName, true, callerClassLoader);

}

catch (Exception ex) {

callerC = null;

}

return callerC;

}

这个方法返回一个Class对象,通过指定的类装载器来装载驱动类。这个方法内做得非常小心,如果出现异常都会把需要返

回的Class对象置为null.

在if语句中调用getCallerClass方法得到的Class 对象和每一个驱动的Class对象比较,不相等的话就继续执行下一次循环

,否则都调用Driver的connect方法,传入url, 和 info,通过这个方法返回Connection连接对象

Connection result = di.driver.connect(url, info);

Driver接口的实现类中的connect方法具体所做的工作将在下一篇中详述

connect 方法是java.sql.Driver接口中定义的方法,如果连接的数据库不同,那么为不同的数据库编写JDBC驱动将变得很灵活,实现Driver接口 即可。连接数据库时首先得装载JDBC驱动,也就是调用 Class.forName(“com.mysql.jdbc.Driver”)方法,在第一篇中已经列出mysql jdbc Driver类的源码,此类继承NonRegisteringDriver同时实现了java.sql.Driver接口。找到 NonRegisteringDriver类会发现它也实现了java.sql.Driver接口:

public class NonRegisteringDriver implements java.sql.Driver {

……

}

在getConnection方法中有如下一句代码,Connection result = di.driver.connect(url, info);

di是DriverInfo类型的对象,此对象中包含了Driver的引用,但是在com.mysql.jdbc.Driver类中只有一个静态块和一个 构造方法,那么connect方法有可能是在其父类中实现。如前所述,父类为NonRegisteringDriver,在mysql驱动包的源码中可以 找到此类,:

com.mysql.jdbc.NonRegisteringDriver

那么di.driver.connect(url, info) 调用的connect方法就是NonRegisteringDriver类中的connect方法,源码如下:

public java.sql.Connection connect(String url, Properties info)

throws SQLException {

if (url != null) {

if (StringUtils.startsWithIgnoreCase(url, LOADBALANCE_URL_PREFIX)) {

return connectLoadBalanced(url, info);

} else if (StringUtils.startsWithIgnoreCase(url,

REPLICATION_URL_PREFIX)) {

return connectReplicationConnection(url, info);

}

}

Properties props = null;

if ((props = parseURL(url, info)) == null) {

return null;

}

try {

Connection newConn = com.mysql.jdbc.ConnectionImpl.getInstance(

host(props), port(props), props, database(props), url);

return newConn;

} catch (SQLException sqlEx) {

// Don't wrap SQLExceptions, throw

// them un-changed.

throw sqlEx;

} catch (Exception ex) {

SQLException sqlEx = SQLError.createSQLException(Messages

.getString("NonRegisteringDriver.17") //$NON-NLS-1$

+ ex.toString()

+ Messages.getString("NonRegisteringDriver.18"), //$NON-NLS-1$

SQLError.SQL_STATE_UNABLE_TO_CONNECT_TO_DATASOURCE, null);

sqlEx.initCause(ex);

throw sqlEx;

}

}

在connect方法中传入了两个参数,一个是String 类型的url, 另一个是Properties类型的连接属性信息。

首先判断url是否为null,此判断逻辑中使用了如下类的方法

调用类com.mysql.jdbc.StringUtils

方法 startsWithIgnoreCase 其中使用了String 类中的方法regionMatches

regionMatches方法两种原型为:

public boolean regionMatches(int toffset, String other,

int ooffset,int len) { }

public boolean regionMatches(boolean ignoreCase, int toffset,

String other, int ooffset, int len) {}

这两个重载的方法用来比较两个字符串中指定区域的子串。

传入的静态常量参数:

private static final String LOADBALANCE_URL_PREFIX = "jdbc:mysql:loadbalance://";

private static final String REPLICATION_URL_PREFIX = "jdbc:mysql:replication://";

根据下面的判断调用不同的方法返回Connection对象

if (StringUtils.startsWithIgnoreCase(url, LOADBALANCE_URL_PREFIX)) {

return connectLoadBalanced(url, info);

} else if (StringUtils.startsWithIgnoreCase(url,

REPLICATION_URL_PREFIX)) {

return connectReplicationConnection(url, info);

}

如果url为null, 则通过如下方法返回Connection

try {

Connection newConn = com.mysql.jdbc.ConnectionImpl.getInstance(

host(props), port(props), props, database(props), url);

return newConn;

} catch (SQLException sqlEx) {

……

} catch (Exception ex) {

……

}

}

未完待续......

java mysql 源码分析_JAVA JDBC(MySQL)驱动源码分析相关推荐

  1. java jdbc(mysql)驱动源码分析_JAVA JDBC(MySQL)驱动源码分析(二)

    本文系转载,地址:http://blog.csdn.net/brilliancezhou/article/details/5425687 上一篇中分析了Class.forName("com. ...

  2. java连接MySQL几种方法_Java连接MySQL数据库三种方法

    好久没有更新博客了!今天利用周目时学习了一下数据库mysql.介绍一下数据库的三种连接方式! 开发工具:Myeclipse MySQL5.6 MySQL连接驱动:mysql-connector-jav ...

  3. java mysql插入数据乱码_java向mysql数据库插入数据显示乱码的问题

    在做一个java web工程时,有时会碰到在向数据库添加数据库时,结果出现乱码"???"的问题.针对该问题的主要解决办法就是: 一.确保是否添加了字符集过滤器: 在java web ...

  4. java插入数据库字符串拼接_java连接mysql数据库实现单条插入和批量插入

    本文实例为大家分享了java连接mysql数据库实现单条和批量插入的具体代码,供大家参考,具体内容如下 本文插入数据库的数据来源:java + dom4j.jar提取xml文档内容 1.连接数据库 p ...

  5. java对mysql进行查找替换_java对mysql的增删改查

    -----连接数据库 package connectdb; import java.sql.*; class Dbcon { // 此处连接数据库,独立开一个类,以后操作数据库的每次连接就不用写这么多 ...

  6. java对mysql进行查找替换_Java对MySQL数据库进行连接、查询和修改【转载】

    一般过程: (1) 调用Class.forName()方法加载驱动程序. (2) 调用DriverManager对象的getConnection()方法,获得一个Connection对象. (3) 创 ...

  7. java 复制mysql某张表_java实现mysql数据库从一张表插入数据到另一张表

    packagecn.gtmc.schedule.app;importcn.gtmc.schedule.domain.Employee;import java.sql.*;importjava.util ...

  8. java实现对mysql数据库的操作_java 对mysql数据库的基本操作

    java对mysql数据库的操作分为以下几个步骤: 1.获取连接: 获取连接需要两步,一是使用DriverManager来注册驱动,二是使用DriverManager来获取Connection对象. ...

  9. java mysql 有什么用_java web mysql 入门知识讲解

     MySQL学习笔记总结 一.SQL概述: SQL:Structured Query Language的缩写(结构化查询语言) SQL工业标准:由ANSI(ISO核心成员) 按照工业标准编写的SQ ...

最新文章

  1. 2021年大数据Flink(十九):案例一 基于时间的滚动和滑动窗口
  2. 【Qt】菜单栏、工具栏、状态栏、右键菜单的实现
  3. 自动驾驶LiDAR点云深度学习综述
  4. Faas 典型场景——应用负载有显著的波峰波谷,典型用例-基于事件的数据处理...
  5. java- 和 || 优先级的问题
  6. 自定义eclipse启动画面
  7. 关于JAVA中URL传递中文参数,取值是乱码的解决办法
  8. 业务实体 数据实体
  9. h5页面 pc端html 调用QQ群
  10. dat14-memcached
  11. 智能家居产品持续发烧 增值应用功能多样化发展
  12. Cisco PIX 简单配置-4
  13. 计算机软件资产代码,事业单位六大类固定资产代码.xls
  14. 一种电力线宽带载波系统采样频偏的估计方法
  15. 【视线追踪】视线追踪的性能评估框架 及 基础知识
  16. Linux通过黑、白名单限制IP登录
  17. Linux常用命令详解(两万字超长文)
  18. 基于74LS148的简单四路抢答器 Multisim
  19. 洛谷 P1719 最大加权矩形
  20. CTF 每日一题 Day44 rot

热门文章

  1. 为什么我们需要TOGAF企业架构?——上海信息化培训中心
  2. Ubuntu: failed to fetch
  3. 重装Intel核显后,设备管理器英特尔显卡属性这里报告了一个未启动设备(igfx)
  4. [Ahoi2014Jsoi2014]骑士游戏(SPFA)
  5. usb接口多少钱_新款本田CRV正式上市,落地价多少钱?
  6. 光遇测试服怎么显示服务器错误,光遇服务器错误怎么办_光遇服务器错误解决方法_3DM手游...
  7. B2G:来自Web平台的挑战者
  8. 如何在Win7安装U盘中加入USB3.0驱动的支持
  9. 20180402-E · US Tuition Costs · ggplot2, 地图 热力图 gganimate 动图 · R 语言数据可视化 案例 源码
  10. 详解python中readlines函数的参数hint