`

参考Mysql JDBC 驱动源码实现自定义驱动

    博客分类:
  • java
 
阅读更多

一、分析Mysql JDBC

平常我们直接以JDBC连接数据库代码基本都如下:

    Connection con = null;  //创建用于连接数据库的Connection对象  
        try {  
            Class.forName("com.mysql.jdbc.Driver");// 加载Mysql数据驱动  
              
            con = DriverManager.getConnection(  
                    "jdbc:mysql://localhost:3306/myuser", "root", "root");// 创建数据连接  
              
        } catch (Exception e) {  
            System.out.println("数据库连接失败" + e.getMessage());  
        }  
        return con; //返回所建立的数据库连接  

 

1、我们使用Mysql JDBC的时候需要先注册加载驱动:

 

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

 

 利用jdk反射机制的真实注册过程如下:

package com.mysql.jdbc;  
  
import java.sql.SQLException;  
public class Driver extends NonRegisteringDriver implements java.sql.Driver {  
      
       //执行这个静态代码块  
    static {  
        try {//注册mysql实现的驱动类  
            java.sql.DriverManager.registerDriver(new Driver());  
        } catch (SQLException E) {  
            throw new RuntimeException("Can't register driver!");  
        }  
    }  
  
    public Driver() throws SQLException {  
        // Required for Class.forName().newInstance()  
    }  
}  

 接着我们进入java.sql.DriverManager.registerDirver(new Driver())源码:

    /**
     * Registers the given driver with the <code>DriverManager</code>.
     * A newly-loaded driver class should call
     * the method <code>registerDriver</code> to make itself
     * known to the <code>DriverManager</code>.
     *
     * @param driver the new JDBC Driver that is to be registered with the
     *               <code>DriverManager</code>
     * @exception SQLException if a database access error occurs
     */
    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();
	drivers.addElement(di);//注册到驱动集合
	println("registerDriver: " + di);
    }

 再进行一些细节的初始化工作驱动就注册加载完成了,有兴趣可自己看源码。接着我们如何创建连接。

 

2、创建数据连接

 

Drivermanager.getConnection(url,name,password)

 我们进去看看这个方法的实际执行过程

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

        // Gets the classloader of the code that called this method, may 
	// be null.
	ClassLoader callerCL = DriverManager.getCallerClassLoader();

	if (user != null) {
	    info.put("user", user);//获取用户名
	}
	if (password != null) {
	    info.put("password", password);//获取密码
	}

        return (getConnection(url, info, callerCL));//①
    }
 接着我们再看①处的代码执行过程
    //  Worker method called by the public getConnection() methods.
    private static synchronized Connection getConnection(
	String url, java.util.Properties info, ClassLoader callerCL) throws SQLException {
	
        /*
	 * When callerCl is null, we should check the application's
	 * (which is invoking this class indirectly)
	 * classloader, so that the JDBC driver class outside rt.jar
	 * can be loaded from here.
	 */
	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();
	}

	// 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;
		}
	    }
	}
 所以上面的①处的代码实际执行的就是com.mysql.jdbc.Driver的connect(url,info)方法
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;  
        }  
  
        if (!"1".equals(props.getProperty(NUM_HOSTS_PROPERTY_KEY))) {  
            return connectFailover(url, info);  
        }  
          
        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;  
        }  
    }  
二、自定义驱动 
		Class.forName("org.tinygroup.dbrouterjdbc3.jdbc.TinyDriver");
		conn = DriverManager.getConnection("jdbc:dbrouter://aggregate", "ljf",
				"123456");
 1、注册加载驱动
public class TinyDriver implements Driver {

    private RouterManager manager;

    private Logger logger = LoggerFactory.getLogger(TinyDriver.class);

    static {
        try {
            DriverManager.registerDriver(new TinyDriver());//注册驱动
        } catch (SQLException E) {
            throw new RuntimeException("Can't register driver!");
        }
    }

    public TinyDriver() {
        manager = RouterManagerBeanFactory.getManager();
    }
 我们再来看看如何获得数据连接
    public Connection connect(String url, Properties info) throws SQLException {
        if (!acceptsURL(url)) {
            return null;
        }
        String routerName = url.substring("jdbc:dbrouter://".length());
        Router router = manager.getRouter(routerName);
        String user = info.getProperty("user");
        String password = info.getProperty("password");
        if (!user.equals(router.getUserName())) {
            logger.logMessage(LogLevel.ERROR,
                    "username {0} and {1} not equals", user,
                    router.getUserName());
            throw new SQLException("username not equals");
        }
        if (!password.equals(router.getPassword())) {
            logger.logMessage(LogLevel.ERROR,
                    "password {0} and {1} not equals", password,
                    router.getPassword());
            throw new SQLException("password not equals");
        }
        return new TinyConnection(routerName);
    }
 通过以上的分析我们可以通过对JDBC进行包装就能做到多数据源,甚至可以在JDBC层上进行分库分表。这样做的好处是对于上层开发人员是透明的。

 

分享到:
评论

相关推荐

    Mysql JDBC源码 官网版

    MySQL Connector/J是官方提供的JDBC驱动程序,它的源代码能帮助开发者深入理解数据库连接、数据传输以及SQL语句在Java中的执行过程。 首先,我们来看看JDBC的概念。JDBC是Java平台上的一个标准接口,由Sun ...

    mysql8驱动源码.zip

    MySQL 8 数据库驱动源码分析 MySQL 是世界上最流行的开源关系型数据库管理系统之一,而 `mysql-connector-java` 是 MySQL 官方提供的用于 Java 应用程序连接到 MySQL 数据库的 JDBC 驱动程序。在 MySQL 8 版本中,...

    java mysql驱动源码

    Java MySQL驱动源码是连接Java应用程序与MySQL数据库的关键组件,其主要实现是通过JDBC(Java Database Connectivity)接口。在Java中,JDBC提供了一组API,使得开发人员能够用标准的Java语言来访问和操作各种数据库...

    mysql jdbc

    关于源码分析,MySQL JDBC驱动的源代码可以提供深入理解数据库连接的工作原理、事务处理、批处理以及错误处理机制等。对于开发者来说,阅读源码有助于优化性能,解决特定问题,或者为自定义功能提供灵感。 在工具...

    mysql驱动包 源码

    `mysql-connector-java-3.1.11`是MySQL提供的特定版本的JDBC驱动程序,用于在Java环境中建立和管理到MySQL服务器的连接。 MySQL JDBC驱动分为四个主要类型: 1. **Type 1 (纯Java驱动)**:这是最早的驱动类型,...

    mysqljdbc src

    在"mysqljdbc src"中,我们探讨的是MySQL JDBC 5的源代码,这为我们提供了深入理解其内部工作原理的机会。 源代码分析通常有助于开发者调试问题、优化性能、学习设计模式以及自定义功能。MySQL JDBC 5源码包含了...

    MySQL的jar包以及源码

    源码分析可以帮助我们了解数据库连接、查询执行、结果集处理等过程的具体实现,这对于优化性能、解决兼容性问题或开发自定义驱动都是很有帮助的。 总之,这个资源对于学习和使用Java与MySQL数据库交互的开发者来说...

    java mysql驱动jar包和zip源码

    如果你想要深入研究JDBC驱动的工作机制,或者想要根据自己的需求修改某些功能,这部分源码将会是宝贵的参考资料。 在实际开发中,确保使用的驱动版本与MySQL服务器版本兼容是非常重要的,因为不同版本的驱动可能...

    java连接mysql数据库(JDBC驱动).pdf

    为了连接到特定的数据库(如MySQL),需要相应的JDBC驱动,例如MySQL Connector/J。在上述描述中提到的JDBC驱动版本3.1.8是用于连接MySQL的。 2. **MySQL下载与安装**: 首先需要下载适合的MySQL服务器版本,如...

    JDBC学习源码与文档

    8. **JDBC驱动**:不同的数据库厂商提供了各自的JDBC驱动,如MySQL的Connector/J,Oracle的JDBC驱动等。了解如何根据不同的数据库选择合适的驱动并进行配置是必要的。 9. **异常处理**:在JDBC编程中,要正确处理`...

    mysql driver

    2. **驱动类型**:如JDBC驱动、ODBC驱动等,根据不同的编程语言选择合适的驱动。 3. **安装与配置**:如何在项目中添加和配置驱动,设置连接参数(如URL、用户名、密码)。 4. **源码分析**:理解驱动内部的工作流程...

    jdbc连mysql数据库

    在描述中提到的“博文链接”(https://jingliankui123.iteye.com/blog/600797)虽然没有具体内容,但通常这样的链接指向一篇博客文章,可能会详细介绍如何配置和使用JDBC连接MySQL,包括下载JDBC驱动、配置数据库...

    java Swing mysql实现简单的购物系统项目源码.rar

    首先,通过`Class.forName()`加载JDBC驱动,然后使用`DriverManager.getConnection()`建立与数据库的连接。接着,可以创建Statement或PreparedStatement对象来执行SQL查询或更新操作。 4. **Swing事件监听**: Swing...

    springmvc4.3+mysql5.6+shardingjdbc2.0.3

    5. 兼容性:ShardingJDBC作为一个JDBC驱动,兼容各种ORM框架,如MyBatis。 在项目源码中,"sancell-bbs"可能是一个名为"Sancell BBS"的论坛系统,它利用上述技术栈实现了数据库分片和Web服务。Myeclipse 2017是一个...

    mysql-connector-java-3.1.14

    1. **JDBC驱动程序**:这是主要的组件,实现了JDBC接口,使Java应用程序能够与MySQL服务器通信。驱动分为两种类型:Type 1(纯Java驱动)和Type 4(网络协议驱动)。MySQL Connector/J是Type 4,它直接使用MySQL的...

    JDBC实现纵向导出数据库数据

    1. **引入JDBC驱动**:首先,确保你的项目中包含了对应数据库的JDBC驱动。例如,如果你使用的是MySQL,那么需要添加MySQL Connector/J的依赖。 2. **建立数据库连接**:使用`DriverManager.getConnection()`方法...

    jsp servlet mysql实现的在线商城项目源码

    JDBC是Java连接数据库的标准接口,项目中通过JDBC驱动与MySQL数据库进行交互,实现数据的读写操作。 7. JSP标签库: 可能使用了JSTL(JavaServer Pages Standard Tag Library)或其他自定义标签库,简化JSP页面的...

    mysql-connector-java-5.0.8.rar

    JDBC驱动分为四种类型,从Type 1到Type 4,Type 4是纯Java实现的网络驱动,无需依赖于本地数据库接口,MySQL Connector/J就是Type 4驱动,它提供高效、高性能的连接。开发者通过JDBC驱动可以在Java代码中编写SQL语句...

    mysql-connector-java-8.0.16-master.zip

    MySQL Connector/J 实现了 JDBC (Java Database Connectivity) 规范,它是 Java 应用程序与 MySQL 服务器之间的桥梁。JDBC 是一个 Java API,允许程序员用标准的 Java 语句来访问和处理关系数据库。MySQL Connector/...

Global site tag (gtag.js) - Google Analytics