`
wu_quanyin
  • 浏览: 208188 次
  • 性别: Icon_minigender_1
  • 来自: 福建省
社区版块
存档分类
最新评论

Mysql JDBC驱动源码分析(获取连接)二

 
阅读更多

setReadonly(true)

 概念:从这一点设置的时间点开始到这个事务结束的过程中,其他事务所提交的数据,该事务将看不见!(查询中不会出现别人在时间点a之后提交的数据)

应用场合:

如果你一次执行单条查询语句,则没有必要启用事务支持,数据库默认支持SQL执行期间的读一致性; 

如果你一次执行多条查询语句,例如统计查询,报表查询,在这种场景下,多条查询SQL必须保证整体的读一致性,否则,在前条SQL查询之后,后条SQL查询之前,数据被其他用户改变,则该次整体的统计查询将会出现读数据不一致的状态,此时,应该启用事务支持。

【注意是一次执行多次查询来统计某些信息,这时为了保证数据整体的一致性,要用只读事务】

怎样设置:

对于只读查询,可以指定事务类型为readonly,即只读事务。

由于只读事务不存在数据的修改,因此数据库将会为只读事务提供一些优化手段,例如Oracle对于只读事务,不启动回滚段,不记录回滚log。

 

 

当驱动加载完毕后,接下来就是怎样去获取一个连接

 

Drivermanager.getConnection(url,name,password)

 跟踪代码执行到以下一步

 

 private static Connection getConnection(
	String url, java.util.Properties info, ClassLoader callerCL) throws SQLException {
	java.util.Vector drivers = null;
        /*
	 * 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.
	 */
	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");
    }

 进入com.mysql.jdbc.Driver下connect(url,info)方法NonRegisteringDriver

 

 

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;
		}
	}
 

 对com.mysql.jdbc.JDBC4Connection的初始化

 

protected static Connection getInstance(String hostToConnectTo,
			int portToConnectTo, Properties info, String databaseToConnectTo,
			String url) throws SQLException {
		if (!Util.isJdbc4()) {
			return new ConnectionImpl(hostToConnectTo, portToConnectTo, info,
					databaseToConnectTo, url);
		}
               //初始化
		return (Connection) Util.handleNewInstance(JDBC_4_CONNECTION_CTOR,
				new Object[] {
							hostToConnectTo, Integer.valueOf(portToConnectTo), info,
							databaseToConnectTo, url }, null);
	}

 进入Jdbc4Connection的代码跟踪

 

 

protected ConnectionImpl(String hostToConnectTo, int portToConnectTo, Properties info,
			String databaseToConnectTo, String url)
			throws SQLException {
		this.charsetToNumBytesMap = new HashMap();
	
		this.connectionCreationTimeMillis = System.currentTimeMillis();
		this.pointOfOrigin = new Throwable();

      if (databaseToConnectTo == null) {
			databaseToConnectTo = "";
		}

		// Stash away for later, used to clone this connection for Statement.cancel
		// and Statement.setQueryTimeout().
		//
		
		this.origHostToConnectTo = hostToConnectTo;
		this.origPortToConnectTo = portToConnectTo;
		this.origDatabaseToConnectTo = databaseToConnectTo;

		try {
			Blob.class.getMethod("truncate", new Class[] {Long.TYPE});
			
			this.isRunningOnJDK13 = false;
		} catch (NoSuchMethodException nsme) {
			this.isRunningOnJDK13 = true;
		}
		
		this.sessionCalendar = new GregorianCalendar();
		this.utcCalendar = new GregorianCalendar();
		this.utcCalendar.setTimeZone(TimeZone.getTimeZone("GMT"));

		this.log = LogFactory.getLogger(getLogger(), LOGGER_INSTANCE_NAME, getExceptionInterceptor());

		// We store this per-connection, due to static synchronization
		// issues in Java's built-in TimeZone class...
		this.defaultTimeZone = Util.getDefaultTimeZone();
		
		if ("GMT".equalsIgnoreCase(this.defaultTimeZone.getID())) {
			this.isClientTzUTC = true;
		} else {
			this.isClientTzUTC = false;
		}

		this.openStatements = new HashMap();
		
		if (NonRegisteringDriver.isHostPropertiesList(hostToConnectTo)) {
			Properties hostSpecificProps = NonRegisteringDriver.expandHostKeyValues(hostToConnectTo);
			
			Enumeration<?> propertyNames = hostSpecificProps.propertyNames();
			
			while (propertyNames.hasMoreElements()) {
				String propertyName = propertyNames.nextElement().toString();
				String propertyValue = hostSpecificProps.getProperty(propertyName);
				
				info.setProperty(propertyName, propertyValue);
			}
		} else {
		
			if (hostToConnectTo == null) {
				this.host = "localhost";
				this.hostPortPair = this.host + ":" + portToConnectTo;
			} else {
				this.host = hostToConnectTo;
				
				if (hostToConnectTo.indexOf(":") == -1) {
					this.hostPortPair = this.host + ":" + portToConnectTo;
				} else {
					this.hostPortPair = this.host;
				}
			}
		}

		this.port = portToConnectTo;

		this.database = databaseToConnectTo;
		this.myURL = url;
		this.user = info.getProperty(NonRegisteringDriver.USER_PROPERTY_KEY);
		this.password = info
				.getProperty(NonRegisteringDriver.PASSWORD_PROPERTY_KEY);

		if ((this.user == null) || this.user.equals("")) {
			this.user = "";
		}

		if (this.password == null) {
			this.password = "";
		}

		this.props = info;
		
		
		
		initializeDriverProperties(info);
		
		
		try {   //获取数据库的信息
			this.dbmd = getMetaData(false, false);
			initializeSafeStatementInterceptors();
                        //======================================创建远程IO连接
			createNewIO(false);
			unSafeStatementInterceptors();
		} catch (SQLException ex) {
			cleanup(ex);

			// don't clobber SQL exceptions
			throw ex;
		} catch (Exception ex) {
			cleanup(ex);

			StringBuffer mesg = new StringBuffer(128);

			if (!getParanoid()) {
				mesg.append("Cannot connect to MySQL server on ");
				mesg.append(this.host);
				mesg.append(":");
				mesg.append(this.port);
				mesg.append(".\n\n");
				mesg.append("Make sure that there is a MySQL server ");
				mesg.append("running on the machine/port you are trying ");
				mesg
						.append("to connect to and that the machine this software is "
								+ "running on ");
				mesg.append("is able to connect to this host/port "
						+ "(i.e. not firewalled). ");
				mesg
						.append("Also make sure that the server has not been started "
								+ "with the --skip-networking ");
				mesg.append("flag.\n\n");
			} else {
				mesg.append("Unable to connect to database.");
			}

			SQLException sqlEx = SQLError.createSQLException(mesg.toString(),
					SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE, getExceptionInterceptor());
			
			sqlEx.initCause(ex);
			
			throw sqlEx;
		}
	}
 

 

 

 

 

 

分享到:
评论

相关推荐

    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-driver:mysql jdbc驱动源码阅读

    在“mysql-driver:mysql jdbc驱动源码阅读”这个主题中,我们将深入探讨该驱动的工作原理、关键组件以及源码分析。 1. **JDBC驱动类型**: JDBC驱动分为四种类型:Type 1、Type 2、Type 3 和 Type 4。MySQL ...

    mysql8驱动和源码.rar

    源码分析对于开发者来说是一个宝贵的学习资源,可以帮助深入理解 MySQL 的内部工作原理。通过查看源码,可以了解 MySQL 如何处理 SQL 语句、管理事务、优化查询、存储和检索数据等。此外,源码分析还能帮助开发者...

    mysqljdbc src

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

    JAVA连mysql源码包JDBC

    压缩包中的“mysql-connector-java-5.1.18--源码”文件是MySQL的JDBC驱动源代码,通过阅读这些源代码,开发者可以深入了解JDBC驱动的工作原理,以及它是如何与MySQL服务器通信的。此外,这也有助于解决在使用过程中...

    JDBC数据连接源码.rar

    这通常通过`Class.forName()`方法完成,例如`Class.forName("com.mysql.jdbc.Driver")`来加载MySQL的JDBC驱动。 2. **建立连接**:使用`DriverManager.getConnection()`方法创建到数据库的连接。参数通常包括数据库...

    eclipse-jdbc连接数据库源码

    Eclipse JDBC连接数据库源码分析 在Java编程中,JDBC(Java Database Connectivity)是用于与各种数据库进行交互的一组接口和类。本资源“eclipse-jdbc连接数据库源码”提供了一系列关于如何使用Eclipse IDE进行...

    MySQL的jar包以及源码

    在Java编程中,我们需要与MySQL数据库进行交互,这时就会用到MySQL的Java连接器,即JDBC驱动。本资源包含了MySQL的JDBC驱动jar包——mysql-connector-java-5.1.37-bin.jar,以及相关的源码,这对于Java开发者来说是...

    JDBC连接ORACLE数据库源码

    ### 二、Oracle JDBC驱动简介 Oracle提供了专门针对其数据库的JDBC驱动程序,该驱动程序使得Java应用程序能够直接与Oracle数据库进行通信。在这个示例中,使用的Oracle JDBC驱动类名为`oracle.jdbc.driver.Oracle...

    mysql-connector-java-5.1.37jar包和源码

    关于源码分析,MySQL Connector/J的源码可以帮助我们深入理解JDBC驱动的工作原理,包括如何建立网络连接、解析SQL语句以及处理结果集等。源码中包含了如`com.mysql.jdbc.Driver`(驱动注册类)、`...

    jdbc分页查询源码

    对于MySQL等支持LIMIT的数据库,分页查询的SQL大致如下: ```sql SELECT * FROM table LIMIT start, pageSize; ``` 这里的`start`表示起始位置(从0开始),`pageSize`表示每页的记录数。 在Java中,使用JDBC进行...

    jdbc接连数据库:oracle/derby/mysql

    标题中的“jdbc连接数据库:oracle/derby/mysql”是指使用Java Database Connectivity (JDBC) API来与三种不同的数据库...同时,了解并分析JDBC驱动源码有助于深入理解数据库操作的底层机制,提升开发和问题排查能力。

    mysql-connector-java-5.1.26源码

    1. **DriverManager**: 这是Java数据库连接的入口点,负责管理所有的JDBC驱动。当Java应用通过`Class.forName()`加载了MySQL的驱动后,`DriverManager`会注册这个驱动,并根据用户提供的URL、用户名和密码建立到...

    JDBC连接数据库实例+附源码

    2. 在Java项目中引入MySQL的JDBC驱动包(例如mysql-connector-java-8.0.16.jar),创建相应的包结构。 3. 定义`Student`实体类,用于表示学生信息。 4. 设计`StudentDao`接口,定义数据库操作方法,如`...

    使用jdbc获取数据库基础信息(附源码)

    首先,我们需要引入JDBC驱动,这通常是通过在Java代码中添加相应的`import`语句完成的。例如,如果你使用的是MySQL数据库,你需要引入如下导入: ```java import java.sql.Connection; import java.sql....

    Jdbc深入分析

    ### Jdbc深入分析 #### 一、JDBC概述与应用场景 **1.1 JDBC概念** JDBC(Java Database Connectivity)是Java中用来对关系型数据库进行访问的一种标准API,它提供了一种统一的方式去访问不同的数据库系统。通过...

Global site tag (gtag.js) - Google Analytics