JDBC解析
来源:互联网 发布:控制面板里没有java 编辑:程序博客网 时间:2024/05/29 02:37
mysql版本:Ver 14.14 Distrib 5.7.16, for Win64 (x86_64)
驱动版本号:5.1.40
所有的JDBC应用程序都具有下面的基本流程:
1、加载数据库驱动。(JDBC4.0版本后依赖service provider默认执行,也就是不再需要使用Class.forName加载驱动)
2、建立到数据库的连接。
3、执行SQL语句。
4、处理结果。
5、从数据库断开连接并释放资源。
接下来,我们依据上述流程作出解释。
1、加载数据库驱动。
try { Class.forName("com.mysql.jdbc.Driver");} catch (ClassNotFoundException e) { e.printStackTrace();}
public class Driver extends NonRegisteringDriver implements java.sql.Driver { static { try { java.sql.DriverManager.registerDriver(new Driver()); } catch (SQLException E) { throw new RuntimeException("Can't register driver!"); } } public Driver() throws SQLException { }}
知道了上述作用,我们当然也可以这样使用Driver driver = new com.mysql.jdbc.Driver();来加载Mysql驱动程序。
当然没有必要,我们没有使用driver。
那么,我们不写可以吗?
测试:
import java.sql.*;/** * Created by N3verL4nd on 2017/4/25. */public class jdbc { public static void main(String[] args) { String driverClass = "com.mysql.jdbc.Driver"; String jdbcUrl = "jdbc:mysql:///test?useUnicode=true&characterEncoding=UTF-8&useSSL=true"; String user = "root"; String password = "lgh123"; String sql = "SELECT * FROM persons"; Connection conn = null; /*try { Class.forName(driverClass); } catch (ClassNotFoundException e) { e.printStackTrace(); }*/ try { conn = DriverManager.getConnection(jdbcUrl, user, password); System.out.println(conn); } catch (SQLException e) { e.printStackTrace(); } finally { if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }}
貌似不可以?由上报错,是因为没有找到所依赖的mysql驱动程序。我们可以这样设置:
D:\N3verL4nd\Desktop>set classpath=D:\Java\test\mysql-connector-java-5.1.40-bin.jar;
D:\N3verL4nd\Desktop>java jdbc
com.mysql.jdbc.JDBC4Connection@6433a2
再来做一个有意思的测试:
将mysql-connector-java-5.1.40-bin.jar的com目录(里面包含驱动的核心文件)解压到当前目录下。
我们把加载驱动的代码注释取消,再执行
jar包只是起到了压缩的作用,内部使用过程中也一定会涉及解压缩操作来调用驱动内部代码。
命令行下使用更能体会程序的运行原理。
接下来分析下DriverManager,它是JDBC里的一个管理驱动的工具类。
private final static CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<>();保存注册过的驱动列表
static { loadInitialDrivers(); println("JDBC DriverManager initialized");}通过系统属性jdbc.drivers加载JDBC驱动程序。
private static void loadInitialDrivers() { String drivers; try { drivers = AccessController.doPrivileged(new PrivilegedAction<String>() { public String run() { return System.getProperty("jdbc.drivers"); } }); } catch (Exception ex) { drivers = null; } AccessController.doPrivileged(new PrivilegedAction<Void>() {//找到所有的拥有权限的java.sql.Driver的实现 public Void run() { ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);//从系统服务中加载驱动 Iterator<Driver> driversIterator = loadedDrivers.iterator(); try{ while(driversIterator.hasNext()) {//遍历驱动 driversIterator.next(); } } catch(Throwable t) { } return null; } }); println("DriverManager.initialize: jdbc.drivers = " + drivers); if (drivers == null || drivers.equals("")) { return; } String[] driversList = drivers.split(":"); println("number of Drivers:" + driversList.length); for (String aDriver : driversList) { try { println("DriverManager.Initialize: loading " + aDriver); Class.forName(aDriver, true, ClassLoader.getSystemClassLoader()); } catch (Exception ex) { println("DriverManager.Initialize: load failed: " + ex); } }}接着判断驱动对象集是否为null,如果为null则返回,否则进入for循环,这个循环会依次遍历多个数据库驱动,因为jdbc:drivers会有多个数据库驱动,驱动名是以:分割,接下来就是通过Class.forName依次装载驱动类,在其中使用了ClassLoader.getSystemClassLoader()系统类装载器。
Driver类的静态代码块关键的一句代码:
java.sql.DriverManager.registerDriver(new Driver());
public static synchronized void registerDriver(java.sql.Driver driver) throws SQLException { registerDriver(driver, null);}
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);}DriverInfo驱动信息类,是一个内部类,实际上就是对Driver的封装。然后再添加到registeredDrivers集合中。
2、建立到数据库的连接。
DriverManager.getConnection()方法来获取连接;我们知道这个是获取一个Connection,那么我们首先来看看DriverManager的getConnection到底做了什么?
public static Connection getConnection(String url)//所有参数全部通过URL传递过去
public static Connection getConnection(String url,String user, String password)//用户名和密码单独传递
public static Connection getConnection(String url,java.util.Properties info)//传递多个参数的K-V结构以上三个建立数据库连接的操作都会调用下边这一个:
private static Connection getConnection(String url, java.util.Properties info, Class<?> caller)
private static Connection getConnection( String url, java.util.Properties info, Class<?> caller) throws SQLException { ClassLoader callerCL = caller != null ? caller.getClassLoader() : null; synchronized(DriverManager.class) {//如果没传递CLassLoader用当前线程的 if (callerCL == null) { callerCL = Thread.currentThread().getContextClassLoader(); } } if(url == null) { throw new SQLException("The url cannot be null", "08001");//没有传递URL,则抛出异常 }//注意这个日志,默认是打印不出来的,程序内部会去判定logWriter是否为空,若为空则不会输出,默认为空 println("DriverManager.getConnection(\"" + url + "\")"); SQLException reason = null; for(DriverInfo aDriver : registeredDrivers) {//循环扫描所有的Drivers if(isDriverAllowed(aDriver.driver, callerCL)) { try { println(" trying " + aDriver.driver.getClass().getName()); Connection con = aDriver.driver.connect(url, info);//调用对应Driver的connect方法,得到Connection对象 if (con != null) { // Success! println("getConnection returning " + aDriver.driver.getClass().getName()); return (con);//如果得到了,则返回Connection } } catch (SQLException ex) { if (reason == null) { reason = ex; } } } else { println(" skipping: " + aDriver.getClass().getName()); } } 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");//没有获取到连接会抛出一个SQLException}
synchronized(DriverManager.class) { if (callerCL == null) { callerCL = Thread.currentThread().getContextClassLoader(); }}
中判断传入的类装载器对象是否存在,如果为null, 通过当前线程来获取上下文类装载器,保证JDBC驱动程序类以外的rt.jar中的类
Connection con = aDriver.driver.connect(url, info);
找到符合的驱动器就可以建立连接了。
3、执行SQL语句。
stmt = conn.createStatement();rs = stmt.executeQuery("SELECT * FROM persons");
4、处理结果。
while (rs.next()) { System.out.println(rs.getInt(1) + " " + rs.getString(2) + " " + rs.getInt(3));}
5、从数据库断开连接并释放资源。
finally { if (rs != null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if (stmt != null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } }}
package com.xiya.test;import java.io.PrintWriter;import java.sql.*;public class Test { public static void main(String[] args) { try { Class.forName("com.mysql.jdbc.Driver"); } catch (ClassNotFoundException e) { e.printStackTrace(); } //遍历加载的驱动程序 /*System.out.println("-----------------------------------------------"); Enumeration<Driver> enumeration = DriverManager.getDrivers(); while (enumeration.hasMoreElements()) { System.out.println(enumeration.nextElement()); } System.out.println("-----------------------------------------------");*/ Connection conn = null; Statement stmt = null; ResultSet rs = null; try { //设置将数据输出到控制台 DriverManager.setLogWriter(new PrintWriter(System.out)); conn = DriverManager.getConnection("jdbc:mysql:///test?useUnicode=true&characterEncoding=UTF-8&useSSL=true", "root", "lgh123"); stmt = conn.createStatement(); rs = stmt.executeQuery("SELECT * FROM persons"); while (rs.next()) { System.out.println(rs.getInt(1) + " " + rs.getString(2) + " " + rs.getInt(3)); } } catch (SQLException e) { e.printStackTrace(); } finally { if (rs != null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if (stmt != null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }}
参考:
http://blog.csdn.net/luanlouis/article/details/29850811
http://blog.csdn.net/brilliancezhou/article/details/5425655
http://blog.csdn.net/xieyuooo/article/details/8502585
- 解析jdbc
- JDBC解析
- 解析JDBC(1)
- 解析JDBC(2)
- 全面解析JDBC(一)
- 全面解析JDBC
- 全面解析JDBC
- 【转】JDBC解析
- 全面解析jdbc
- 全面解析JDBC
- 全面解析JDBC
- 全面解析 JDBC
- 全面解析JDBC
- 全面解析JDBC
- 全面解析JDBC
- JDBC实现与解析
- JDBC的自我解析
- storm-jdbc解析
- 【Web系统优化-分布式集群】亿级Web系统搭建——单机到分布式集群
- Servlet.init() for servlet mvc-dispatcher threw exception
- Stacking
- 接收到推送消息处理方法
- 设计模式——工厂模式
- JDBC解析
- Map控件介绍
- Android中引入其他字体库
- PL/SQL破解方法
- iOS 屏幕左侧向右滑动返回
- 彻底掌握Quartus——Signaltap篇
- 【Unity3D】Unity3D 4.x利用原生UGUI完成下拉列表DropDownList
- java.lang.IllegalArgumentException: There is no shards to execute shard operation: 错误原因
- 童年野味——“茅yi”