我是靠谱客的博主 犹豫蚂蚁,最近开发中收集的这篇文章主要介绍Java学习不走弯路教程(5.写一个JDBC驱动),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

写一个JDBC驱动

一. 前言

在前上一章教程中,介绍了用SQL查询远程文件。
本章将在上一章的基础上,进一步扩展程序。

注:
1.本文针对初学Java的同学训练学习思路,请不要太纠结于细节问题。
2.本文旨在达到抛砖引玉的效果,希望大家扩展本例子,以学到更多知识的精髓。

学习本章需要准备的知识:
1.读完本系列教程的前面章节。
2.理解JDBC。

二. 步入正题

话不多说,大家自己理解,下面步入正题:

既然使用SQL查询文件,那么我们可以为这个程序写一个JDBC驱动,这样就能象访问数据库一样访问文件了。
下面我带大家一步一步实现JDBC的驱动程序。

JDBC(Java Database Connectivity)是Java提供的一套与数据库交互的规范,该规范用接口形式来描述,
即如果你的产品要允许Java程序员通过JDBC规范(接口)来进行访问,那么你必须提供一套符合该规范(接口)的驱动程序。

JDBC规范的相关接口都在java.sql包中定义。
最常见接口有:
java.sql.Driver:驱动程序规范
java.sql.Connection:与数据库连接的相关操作
java.sql.Statement:与数据库进行SQL交互的相关操作
java.sql.ResultSet:对查询结果的相关操作

常见的操作如下:

 1 //加载驱动程序
 2 Class.forName("com.mysql.jdbc.Driver");
 3 //连接数据库
 4 Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/DB", "testuser", "testpass");
 5 //创建执行SQL的类
 6 Statement st = conn.createStatement();
 7 //执行SQL,查询结果
 8 ResultSet rs = st.executeQuery("select * from xxx");
 9
10 //遍历查询结果
11 while(rs.next()) {
12
System.out.print(rs.getString(1));
13 }
14
15 //关闭资源
16 rs.close();
17 st.close();
18 conn.close();

 

下面依次介绍程序写法:
1.加载驱动程序
用Class.forName方式加载,即执行目标类的静态块,把驱动程序放在静态块中,保证了该驱动只被加载一次的特性。
另外一个好处是驱动类的名字是用字符串传入的,在工程编译阶段不依赖具体的驱动程序。

获得数据库连接是一切操作开始的根源,在JDBC规范中,用如下方式来获取数据库的连接:
DriverManager.getConnection(...)

我们可以通过源代码看一下DriverManager.getConnection的大致流程:
源代码如下:

 1
private static Connection getConnection(
 2
String url, java.util.Properties info, Class<?> caller) throws SQLException {
 3
/*
 4 
* When callerCl is null, we should check the application's
 5 
* (which is invoking this class indirectly)
 6 
* classloader, so that the JDBC driver class outside rt.jar
 7 
* can be loaded from here.
 8
*/
 9
ClassLoader callerCL = caller != null ? caller.getClassLoader() : null;
10
synchronized(DriverManager.class) {
11
// synchronize loading of the correct classloader.
12
if (callerCL == null) {
13
callerCL = Thread.currentThread().getContextClassLoader();
14 
}
15 
}
16
17
if(url == null) {
18
throw new SQLException("The url cannot be null", "08001");
19 
}
20
21
println("DriverManager.getConnection("" + url + "")");
22
23
// Walk through the loaded registeredDrivers attempting to make a connection.
24
// Remember the first exception that gets raised so we can reraise it.
25
SQLException reason = null;
26
27
for(DriverInfo aDriver : registeredDrivers) {
28
// If the caller does not have permission to load the driver then
29
// skip it.
30
if(isDriverAllowed(aDriver.driver, callerCL)) {
31
try {
32
println("
trying " + aDriver.driver.getClass().getName());
33
Connection con = aDriver.driver.connect(url, info);
34
if (con != null) {
35
// Success!
36
println("getConnection returning " + aDriver.driver.getClass().getName());
37
return (con);
38 
}
39
} catch (SQLException ex) {
40
if (reason == null) {
41
reason = ex;
42 
}
43 
}
44
45
} else {
46
println("
skipping: " + aDriver.getClass().getName());
47 
}
48
49 
}
50
51
// if we got here nobody could connect.
52
if (reason != null)
{
53
println("getConnection failed: " + reason);
54
throw reason;
55 
}
56
57
println("getConnection: no suitable driver found for "+ url);
58
throw new SQLException("No suitable driver found for "+ url, "08001");
59
}

首先遍历已经注册的驱动程序,
用连接字符串,用户名,密码作为参数来调用每个驱动程序的connect方法,
如果该驱动程序返回结果不是null,则认为找到该驱动程序,并且返回使用该驱动程序生成的与数据库的连接。

所以,我们必须首先在DriverManager中注册我们的驱动程序。
我们写一个符合java.sql.Driver的类,如下:

 1 public class MyDriver implements Driver{
 2
 3
static {
 4
try {
 5
// 注册驱动程序
 6
DriverManager.registerDriver(new MyDriver());
 7
} catch (SQLException e) {
 8 
e.printStackTrace();
 9 
}
10 
}
11 ......


2.连接数据库
接下来,要通过传入的连接字符串和用户名密码信息来连接数据库。
在connect()方法判断是否是合法的连接字符串,如果是则连接数据库并返回自定义的MyConnection。

 1
/**
 2 
* @author http://www.java123.vip
 3 
*
 4 
* @param url
 5 
* @param info
 6
*/
 7
public Connection connect(String url, Properties info) throws SQLException {
 8
 9
String protocal = url.split(":")[0];
10
String productor = url.split(":")[1];
11
12
// 只处理连接字符串包括jdbc和my的请求
13
if("jdbc".equals(protocal) && "my".equals(productor)) {
14
String ip = url.split(":")[2];
15
int port = Integer.valueOf(url.split(":")[3]).intValue();
16
String username = info.getProperty("user");
17
String password = info.getProperty("password");
18
19
MyConnection myConnection = new MyConnection(ip,port,username,password);
20
21
return myConnection;
22
} else {
23
return null;
24 
}
25
26
27 
}
28
29 ......其他接口略


3.创建执行SQL的类

MyConnection的构造方法中,初始化输入输出流,用来与远程数据库进行通讯。
在createStatement()方法中,用输入输出流作为参数初始化并返回自定义的MyStatement。

 1 /**
 2  *
 3  * @author http://www.java123.vip
 4  *
 5
*/
 6 public class MyConnection implements Connection{
 7
 8
private Socket socket;
 9
private BufferedReader br;
10
private PrintWriter pw;
11
12
public MyConnection(String ip, int port, String username, String password) {
13
14
try {
15
16
socket = new Socket(ip, port);
17
InputStream is = socket.getInputStream();
18
InputStreamReader isr = new InputStreamReader(is);
19
br = new BufferedReader(isr);
20
21
OutputStream os = socket.getOutputStream();
22
OutputStreamWriter osw = new OutputStreamWriter(os);
23
pw = new PrintWriter(osw,true);
24
25
} catch (IOException e) {
26 
e.printStackTrace();
27 
}
28
29 
}
30
31
public Statement createStatement() throws SQLException {
32
MyStatement st = new MyStatement(br,pw);
33
return st;
34 
}
35
36
public void close() throws SQLException {
37
38
try {
39
pw.println("bye:bye");
40 
socket.close();
41
} catch (IOException e) {
42 
e.printStackTrace();
43 
}
44
45 
}
46 ......其他接口略

4.执行SQL,查询结果
在MyStatement的作一个executeQuery()方法,将传入的sql发送给远程数据库,并且将返回的结果封装成自定义的结果及MyResultSet,
我们延用上一章的方法,向服务器发送查询请求,并且将结果保存在MyResultSet中:
代码如下:

 1 /**
 2  *
 3  * @author http://www.java123.vip
 4  *
 5
*/
 6 public class MyStatement implements Statement{
 7
 8
private BufferedReader br;
 9
private PrintWriter pw;
10
11
public MyStatement(BufferedReader br,PrintWriter pw) {
12
this.br = br;
13
this.pw = pw;
14 
}
15
16
public ResultSet executeQuery(String sql) throws SQLException {
17
18
MyResultSet mrs = new MyResultSet();
19
20
try {
21
pw.println("query:"+sql);
22
23
while(true) {
24
String queryResultLine = br.readLine();
25
26
if("".equals(queryResultLine)) {
27
break;
28
}else {
29
mrs.addData(queryResultLine.split(","));
30 
}
31 
}
32
} catch (IOException e) {
33 
e.printStackTrace();
34 
}
35
36
return mrs;
37 
}
38 ......其他接口略

 

5.遍历查询结果
我们做一个MyResultSet来实现对查询结果的存取操作,代码如下:

 1 /**
 2  *
 3  * @author http://www.java123.vip
 4  *
 5
*/
 6 public class MyResultSet implements ResultSet{
 7
 8
private List<String[]> dataList = new ArrayList<String[]>();
 9
private int cursor = -1;
10
11
public MyResultSet() {
12
13 
}
14
15
public void addData(String[] data) {
16 
dataList.add(data);
17 
}
18
19
public boolean next() throws SQLException {
20
if(cursor + 1 >= dataList.size()) {
21
return false;
22
}else {
23
cursor ++ ;
24
return true;
25 
}
26 
}
27
28
public void close() throws SQLException {
29
30 
}
31
32
public String getString(int columnIndex) throws SQLException {
33
String[] rowData = dataList.get(cursor);
34
return rowData[columnIndex-1];
35 
}
36 ......其他接口略

 

三. 测试
测试程序如下:

 1 /**
 2  *
 3  * @author http://www.java123.vip
 4  *
 5
*/
 6 public class FileViewClientJDBC {
 7
 8
public static void main(String[] args) {
 9
10
try {
11
Class.forName("vip.java123.fileview.client.jdbc.dirver.MyDriver");
12
Connection conn = DriverManager.getConnection("jdbc:my:127.0.0.1:8000", "testuser", "testpass");
13
Statement st = conn.createStatement();
14
ResultSet rs = st.executeQuery("select * from abc.csv");
15
16
while(rs.next()) {
17
System.out.print(rs.getString(1) + ",");
18
System.out.print(rs.getString(2) + ",");
19
System.out.println(rs.getString(3));
20 
}
21
22 
rs.close();
23 
st.close();
24 
conn.close();
25
26
} catch (ClassNotFoundException e) {
27 
e.printStackTrace();
28
} catch (SQLException e) {
29 
e.printStackTrace();
30 
}
31 
}
32 }

 

启动服务器,输出如下:

listening at port:8000

 

启动测试程序,输出如下:

1,abc,aaa
2,def,bbb
3,xyz,ccc

 

服务器输出

listening at port:8000
get connection:/127.0.0.1
get message:query:select * from abc.csv
get message:bye:bye

 

完整程序请大家从[这里]下载

如有问题,大家来我的网站进行提问。
https://www.java123.vip/qa

版权声明:本教程版权归java123.vip所有,禁止任何形式的转载与引用。

转载于:https://www.cnblogs.com/java123-vip/p/9744782.html

最后

以上就是犹豫蚂蚁为你收集整理的Java学习不走弯路教程(5.写一个JDBC驱动)的全部内容,希望文章能够帮你解决Java学习不走弯路教程(5.写一个JDBC驱动)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(44)

评论列表共有 0 条评论

立即
投稿
返回
顶部