1.Sun公司在数据库的链接方式中只定义了接口java.sql.Driver,并未提供对各个数据库产品的链接实现方式,并且要求各数据库厂商在实现java.sql.Driver接口的同时,要将驱动类注册到java.sql.DriverManager中。
1)譬如mysql怎么把驱动类注册到DriverManager,通过静态代码块调用DriverManager注册方法进行注册
com.mysql.cj.jdbc.Driver,最重要的方法也就是建立连接Connection connect(String url, java.util.Properties info),所以连接池的建立连接都要调用这个方法
static { try { java.sql.DriverManager.registerDriver(new Driver()); } catch (SQLException E) { throw new RuntimeException("Can't register driver!"); } }
registerDriver其实是把驱动放进CopyOnWriteArrayList里
private final static CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<>(); public static synchronized void registerDriver(java.sql.Driver driver, DriverAction da) throws SQLException { /* Register the driver if it has not already been added to our list */ if(driver != null) { registeredDrivers.addIfAbsent(new DriverInfo(driver, da)); } else { // This is for compatibility with the original DriverManager throw new NullPointerException(); } println("registerDriver: " + driver); }
2.Druid或者说其他连接池怎么加载Driver,或者我们自己用jdbc怎么加载Drvier,用类加载器把对应数据库的Driver加载进来
Druid的实现,其他也类似
public static Driver createDriver(ClassLoader classLoader, String driverClassName) throws SQLException { Class<?> clazz = null; if (classLoader != null) { try { clazz = classLoader.loadClass(driverClassName); } catch (ClassNotFoundException e) { // skip } } if (clazz == null) { try { ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); if (contextLoader != null) { clazz = contextLoader.loadClass(driverClassName); } } catch (ClassNotFoundException e) { // skip } } if (clazz == null) { try { clazz = Class.forName(driverClassName); } catch (ClassNotFoundException e) { throw new SQLException(e.getMessage(), e); } } try { return (Driver) clazz.newInstance(); } catch (IllegalAccessException e) { throw new SQLException(e.getMessage(), e); } catch (InstantiationException e) { throw new SQLException(e.getMessage(), e); } }
3.我们拿到连接,怎么执行sql,怎么设置事务,跟Driver一样,sun提供了一个接口java.sql.Connection,各大厂商实现
例如:mysql的实现类是这个com.mysql.cj.jdbc.ConnectionImpl,怎么执行sql,加载mysql的Drvier,调用connect拿到的连接就是ConnectionImpl的实例,剩下的sql执行,不用说都是用mysql的实现
public java.sql.Connection connect(String url, Properties info) throws SQLException { try { if (!ConnectionUrl.acceptsUrl(url)) { /* * According to JDBC spec: * The driver should return "null" if it realizes it is the wrong kind of driver to connect to the given URL. This will be common, as when the * JDBC driver manager is asked to connect to a given URL it passes the URL to each loaded driver in turn. */ return null; } ConnectionUrl conStr = ConnectionUrl.getConnectionUrlInstance(url, info); switch (conStr.getType()) { case SINGLE_CONNECTION: return com.mysql.cj.jdbc.ConnectionImpl.getInstance(conStr.getMainHost()); case FAILOVER_CONNECTION: case FAILOVER_DNS_SRV_CONNECTION: return FailoverConnectionProxy.createProxyInstance(conStr); case LOADBALANCE_CONNECTION: case LOADBALANCE_DNS_SRV_CONNECTION: return LoadBalancedConnectionProxy.createProxyInstance(conStr); case REPLICATION_CONNECTION: case REPLICATION_DNS_SRV_CONNECTION: return ReplicationConnectionProxy.createProxyInstance(conStr); default: return null; } } catch (UnsupportedConnectionStringException e) { // when Connector/J can't handle this connection string the Driver must return null return null; } catch (CJException ex) { throw ExceptionFactory.createException(UnableToConnectException.class, Messages.getString("NonRegisteringDriver.17", new Object[] { ex.toString() }), ex); } }