Properties info = new Properties();
info.setProperty("user", "root");
info.setProperty("password", "850656");
info.setProperty("agentID", "1001");
info.setProperty("dbName", "mysql");
// 载入自定义的驱动
Class.forName("com.fanruan.myJDBC.driver.MyDriver");
Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test", info);
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("select * from `student`");
复制代码
如上,由于我重写了JDBC驱动,也就是上文的com.fanruan.myJDBC.driver.MyDriver
。重写的效果大概是通过RPC调用客户端的JDBC执行相应操作。由于RPC调用的需要,在DriverManager.getConnection(String url, Properties info)
中多封装了两个参数,agentID
和dbName
方便 Agent 对于收到的调用消息进行分发。测试运行时,在客户端显示如下:
写的程序有bug我已经习惯了,但是令我费解的是,我明明在 url
中指明了数据库为 test
, 为何会报错说Table 'mysql.student' doesn't exist
呢?
已知建立连接最终调用的是connect
方法:
public java.sql.Connection connect(String url, Properties info) throws SQLException {
...
}
复制代码
mysql
的JDBC实现中,会对传入的 Properties 参数进行解析
public ConnectionImpl(HostInfo hostInfo) throws SQLException {
...
this.database = hostInfo.getDatabase();
...
复制代码
public String getDatabase() {
// 在 PropertyKey 中刚好有个叫 dbname 的键
String database = this.hostProperties.get(PropertyKey.DBNAME.getKeyName());
return isNullOrEmpty(database) ? "" : database;
}
复制代码
导致本来已经被解析为test
的database
:
被覆盖成了mysql
导致了上面所说的错误。
可以看到进入getConnectionURLInstance
时,dbName
还是驼峰命名。
被处理为connectionURL
之后就变成了dbname
,这也是上面覆盖database
的前置条件。
至于为什么,那是因为解析DBNAME的时候设置的是大小写不敏感: