JDBC connection acquisition: http://donald-draper.iteye.com/blog/2342011
Mysql load balancing connection acquisition: http: //donald-draper.iteye.com/blog/2342089
Mysql master-slave replication read-write separation connection acquisition: http://donald-draper.iteye.com/blog/2342108
ConnectionImp creates MysqlIO: http://donald-draper .iteye.com/blog/2342959
Mysql precompiled SQL: http://donald-draper.iteye.com/blog/2342960
MysqlSQL PreparedStatement Query: http://donald-draper.iteye.com/blog/2343083
MySQL ServerPreparedStatement Query: http://donald-draper.iteye.com/blog/2343124
When using hibernate and mybatis as the persistence layer, shield the jdbc stuff. Now that we have time, let's take a look at the underlying jdbc stuff.
First create a mysql test instance as follows;
test instance:
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.Statement; import java.sql.Timestamp; import java.util.Date; public class testMysqlX { public static void main(String[] args){ testMysqlConnection(); } @SuppressWarnings("deprecation") public static void testMysqlConnection() { Connection con = null;// Create a database connection PreparedStatement pre = null;// Create a precompiled statement object, generally use this instead of Statement ResultSet result = null;// Create a result set object try { Class.forName("com.mysql.jdbc.Driver");// Load the driver System.out.println("Start trying to connect to the database!"); String url = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8"; String user = "root";//User name, the system default account name String password = "123456";//The password you set during installation long startTime = System.currentTimeMillis(); con = DriverManager.getConnection(url, user, password);// Get the connection PreparedStatement ps = con.prepareStatement("select count(*) from ?"); ps.setString(1, "user"); result = ps.executeQuery(); //result The initial cursor is head, move next to the first record while(result.next()){ int sum = result.getInt(1); System.out.println("============sum:"+sum); } long endTime = System.currentTimeMillis(); System.out.println("============time:"+ (endTime-startTime)); System.out.println("============hashCode:"+ con.hashCode()); if(!con.isClosed()){ System.out.println("============Connection succeeded!"); } } catch (Exception e) { System.out.println("============Connection failed: "+e.getMessage()); e.printStackTrace (); } finally { try { // Close the above objects one by one, because not closing them will affect performance and occupy resources // Note the order of closing, the last used closes first if (result != null) result.close(); if (pre != null) pre.close(); if (con != null) con.close(); System.out.println("Database connection closed!"); } catch (Exception e) { e.printStackTrace (); } } } }
Let's take a look at the whole process of loading from the driver, getting the connection, getting the PreparedStatement, executing the query, and processing the result set; let's look at the
loading driver and start with
this sentence:
Class.forName("com.mysql.jdbc.Driver");
//Class
public final class Class<T> implements java.io.Serializable, java.lang.reflect.GenericDeclaration, java.lang.reflect.Type, java.lang.reflect.AnnotatedElement { private static final int ANNOTATION= 0x00002000; private static final int ENUM = 0x00004000; private static final int SYNTHETIC = 0x00001000; private static native void registerNatives(); static { registerNatives(); } //Load the corresponding class according to the class name public static Class<?> forName(String className) throws ClassNotFoundException { return forName0(className, true, ClassLoader.getCallerClassLoader()); } /** Called after security checks have been made. */ private static native Class forName0(String name, boolean initialize, ClassLoader loader) throws ClassNotFoundException; }
Take a look at the Driver class of mysql
//com.mysql.jdbc.Driver
public class Driver extends NonRegisteringDriver implements java.sql.Driver { public Driver() throws SQLException { } static { try { //Register the driver to the driver manager DriverManager.registerDriver(new Driver()); } catch(SQLException E) { throw new RuntimeException("Can't register driver!"); } } }
//DriverManager
public class DriverManager { /* write copy of the drivers vector */ private static java.util.Vector writeDrivers = new java.util.Vector(); /* write copy of the drivers vector */ private static java.util.Vector readDrivers = new java.util.Vector(); private static int loginTimeout = 0; private static java.io.PrintWriter logWriter = null; private static java.io.PrintStream logStream = null; private static boolean initialized = false; //register the driver public static synchronized void registerDriver(java.sql.Driver driver) throws SQLException { if (!initialized) { initialize(); } //Initialize driver information DriverInfo in = new DriverInfo(); di.driver = driver; di.driverClass = driver.getClass(); di.driverClassName = di.driverClass.getName (); //Add driver information to the writeDrivers collection writeDrivers.addElement(di); println("registerDriver: " + di); //Clone writeDrivers to readDrivers readDrivers = (java.util.Vector) writeDrivers.clone(); } //initialization static void initialize() { if (initialized) { return; } initialized = true; //Load driver, initialize loadInitialDrivers(); println("JDBC DriverManager initialized"); } //load driver 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 placed in a jar package and loaded through the type loader, all Drivers, each java.sql.Driver.class is a Service DriverService ds = new DriverService(); //Get access to all drivers 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); //load driver Class.forName(driver, true, ClassLoader.getSystemClassLoader()); } catch (Exception ex) { println("DriverManager.Initialize: load failed: " + ex); } } } class DriverService implements java.security.PrivilegedAction { Iterator ps = null; public DriverService() {}; public Object run() { // uncomment the followin line before mustang integration // Service s = Service.lookup(java.sql.Driver.class); // ps = s.iterator(); //Load all Drivers through Service ps = Service.providers(java.sql.Driver.class); /* Load these drivers, so that they can be instantiated. * It may be the case that the driver class may not be there * i.e. there may be a packaged driver with the service class * as implementation of java.sql.Driver but the actual class * may be missing. In that case a sun.misc.ServiceConfigurationError * will be thrown at runtime by the VM trying to locate * and load the service. * * Adding a try catch block to catch those runtime errors * if driver not available in classpath but it's * packaged as service and that service is there in classpath. */ try { while (ps.hasNext()) { //Initialize Driver ps.next(); } // end while } catch(Throwable t) { // Do nothing } return null; } //end run } //end DriverService //Driver information class class DriverInfo { Driver driver; Class driverClass; String driverClassName; public String toString() { return ("driver[className=" + driverClassName + "," + driver + "]"); } }
It can be seen from the initialization process of DriverManager that the loading of Driver is delegated to DriverService, and DriverService is
loaded through Service. Let's take a look at Service
public final class Service { //Load the driver and delegate to providers(Class class1, ClassLoader classloader) public static Iterator providers(Class class1) throws ServiceConfigurationError { ClassLoader classloader = Thread.currentThread().getContextClassLoader(); return providers(class1, classloader); } public static Iterator providers(Class class1, ClassLoader classloader) throws ServiceConfigurationError { //Actually returned is an Iterator, LazyIterator is the static inner class of Service return new LazyIterator(class1, classloader); } //LazyIterator, lazy loading driver collection private static class LazyIterator implements Iterator { public boolean hasNext() throws ServiceConfigurationError { if(nextName != null) return true; if(configs == null) try { String s = (new StringBuilder()).append("META-INF/services/").append(service.getName()).toString(); if(loader == null) configs = ClassLoader.getSystemResources(s); else configs = loader.getResources(s); } catch(IOException ioexception) { Service.fail(service, (new StringBuilder()).append(": ").append(ioexception).toString()); } for(; pending == null || !pending.hasNext(); pending = Service.parse(service, (URL)configs.nextElement(), returned)) if(!configs.hasMoreElements()) return false; nextName = (String)pending.next(); return true; } //The next function is called in DriverService, and loads the driver by traversing the LazyIterator public Object next() throws ServiceConfigurationError { String s; Class class1; if(!hasNext()) throw new NoSuchElementException(); s = nextName; nextName = null; class1 = null; try { class1 = Class.forName(s, false, loader); } catch(ClassNotFoundException classnotfoundexception) { Service.fail(service, (new StringBuilder()).append("Provider ").append(s).append(" not found").toString()); } if(!service.isAssignableFrom(class1)) Service.fail(service, (new StringBuilder()).append("Provider ").append(s).append(" not a subtype").toString()); return service.cast(class1.newInstance()); Throwable throwable; throwable; Service.fail(service, (new StringBuilder()).append("Provider ").append(s).append(" could not be instantiated: ").append(throwable).toString(), throwable); return null; } public void remove() { throw new UnsupportedOperationException(); } Class service; ClassLoader loader; Enumeration configs; Iterator pending; Set returned; String nextName; private LazyIterator(Class class1, ClassLoader classloader) { configs = null; pending = null; returned = new TreeSet(); nextName = null; service = class1; loader = classloader; } private static void fail(Class class1, String s, Throwable throwable) throws ServiceConfigurationError { ServiceConfigurationError serviceconfigurationerror = new ServiceConfigurationError((new StringBuilder()).append(class1.getName()).append(": ").append(s).toString()); serviceconfigurationerror.initCause(throwable); throw serviceconfigurationerror; } //Processing of driver loading failure, throwing an exception private static void fail(Class class1, String s) throws ServiceConfigurationError { throw new ServiceConfigurationError((new StringBuilder()).append(class1.getName()).append(": ").append(s).toString()); } private static void fail(Class class1, URL url, int i, String s) throws ServiceConfigurationError { fail(class1, (new StringBuilder()).append(url).append(":").append(i).append(": ").append(s).toString()); } }
//ServiceConfigurationError
public class ServiceConfigurationError extends Error { public ServiceConfigurationError(String s) { super(s); } public ServiceConfigurationError(Throwable throwable) { super(throwable); } }
At this point, the loading of the driver is over. Let's review the whole process. The Class loads com.mysql.jdbc.Driver, and com.mysql.jdbc.Driver registers the Driver to the DriverManager through the static statement block. The DriverManager first checks whether it is initialized or not. Then load the driver class. The entire driver loading process is through the
DriverService , and the DriverService is delegated to the Service. The Service loads the driver and returns all the Iterators implemented by java.sql.Driver. The Iterator is LazyIterator. Drive; finally wrap the Driver into DriverInfo, add it to the writeDrivers collection, and clone it to readDrivers.