赞
踩
大部分情况下,我们只需要在配置文件中配置数据库的连接,包括url、username、password等基本连接信息,还可以配置数据库连接池大小、最小连接数、超时时间等信息。之后就能连接到数据库进行一系列的操作了。底层是如何做到的并不关心,本节主要是帮助我们了解在我们的代码和数据库之间的一小部分内容。
先解释桥接模式:
假使A是接口, SubA()是实现,类的属性赋值使用多态的方式
//伪代码
class Bridge{
private A a = null;
setA(){ a = SubA()}
method(){
a.method();
}
}
某个类Bridge定义A接口的属性,在方法里面调用接口的方法,实际调用的是实现类的接口
上述就可以在只实现SubA类的情况下,达到抽象和实现分离的目的,JDBC的设计完全符合我们对不同数据库的统一封装,实现则是由各个厂商负责的解耦的风格。
通过setA()的方法对属性进行赋值,最终调用的就是实现了A接口的类的方法了!
桥接模式是设计Java虚拟机和实现JDBC等驱动程序的核心模式之一,应用较为广泛
下面重点来看JDBC流程,证明JDBC的桥接模式
jdk提供接口,厂商按照接口实现
这里只截取了jdk1.8的java.sql 下的Interface 和 class
其中有几个熟悉的
Statement PrepareStatement 和 CallableStatement,这些是JDBC和它的三大对象,它们有各自的含义
ResultSet结果集,主要是存储上述三大对象查询出来的结果。
Connection 和 Driver 比较重要
javax.sql.* 下
通常我们使用的Mysql的驱动都是com.mysql.cj.jdbc.Driver
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
可能有些童鞋对com.mysql.jdbc.Driver也很熟悉。 它是com.mysql.cj.jdbc.Driver的子类
各厂商负责实现接口
mysql-connector-java/8.0.18/mysql-connector-java-8.0.18.jar 这个就是JDBC的驱动,我们既可以直接使用驱动去连接数据库(不推荐),也可以将连接交给连接池去维护,还可以将数据源datasource交给框架去管理。
com.mysql.cj.jdbc.Driver
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 {
// Required for Class.forName().newInstance()
}
}
那什么时候能触发到com.mysql.cj.jdbc.Driver的创建呢?
因为是静态代码块,所以只要Driver类被加载到虚拟机中,那么静态代码块中的代码就会执行!
public static Connection getConnection() throws Exception {
InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
Properties pros = new Properties();
pros.load(is);
String user = pros.getProperty("user");
String password = pros.getProperty("password");
String url = pros.getProperty("url");
String driverClass = pros.getProperty("driverClass");
Connection conn = DriverManager.getConnection(url, user, password);// 这个只有mysql驱动
return conn;
}
DriverManager.getConnection方法,遍历registeredDrivers,这个是之前驱动Driver最终注册到的属性,所以实际在方法调用了驱动中实现类的方法 == 恰恰符合了桥接模式,只不过上面是类,这里是List。核心思想是相同的
CopyOnWriteArrayList registeredDrivers = new CopyOnWriteArrayList<>();
//==getConnection==方法 for(DriverInfo aDriver : registeredDrivers) { // If the caller does not have permission to load the driver then // skip it. if(isDriverAllowed(aDriver.driver, callerCL)) { try { println(" trying " + aDriver.driver.getClass().getName()); Connection con = aDriver.driver.connect(url, info); if (con != null) { // Success! println("getConnection returning " + aDriver.driver.getClass().getName()); return (con); } } catch (SQLException ex) { if (reason == null) { reason = ex; } } } else { println(" skipping: " + aDriver.getClass().getName()); } }
下面是驱动mysql-connector-java包下的文件,采用SPI的方式启动的。在DriverManager类的静态代码块中,触发了SPI方式的创建,加载Driver类,会执行Driver中的静态代码块,将本类注册到了DriverManager的属性中
static {
loadInitialDrivers();
println("JDBC DriverManager initialized");
}
上述是数据库直连的方式实现的。当然也可以使用c3p0、dbcp、druid、Hikari等方式。
至此,我们大致了解了Mysql数据库驱动是如何协同在JDBC下工作的,也了解JDBC桥接模式实现的方式。这可以更好的帮助我们理解JDBC和数据库整合在一起的方式。我认为有些知识是为了更好的理解更高深的内容存在的,不是你学会它就一定能解决什么样的问题。这也是我为什么使用直连的方式的原因,更加直观和清晰。希望能对您有帮助!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。