我实现的内存数据库JDBC驱动

我去年做了个内存数据库,自以为功能很强大。内存数据库是独立运行的程序,客户端通过socket访问,传送SQL语句并得到结果,为此我提供了一个C接口的客户端API。

但如果要做到更好的通用性,必须照顾IT世界数量最多的两类人:java程序员和c#程序员。c#我的同事封装了ado.net驱动。这几天我实现了jdbc的驱动,本文记录实现过程的一些心得。

本人较为擅长的是C/C++,对java的啰嗦语法实在不太感冒,,前阵子用java写过一个规模不大的android程序,才敢挑战写一个jdbc驱动的任务。

我的开发环境是比较小众的mac os x,正好考验一下java所谓的跨平台。

第一步,先将C接口的客户端API封装成一个java类:LxjDbApi.java

package com.lxjdb.jdbc;public class LxjDbApi {public LxjDbApi(){System.loadLibrary("LxjDbJdbcApi");}public native long Open(String host, int port, String user, String pwd);public native void Close(long conn);public native int Exec(long conn, String sql, String[] dbInfo); // 执行一个sql语句public native int Rows(long conn); // 总行数public native int Cols(long conn); // 总列数// 得到列信息public native int GetColInfoByIndex(long conn, int col, String[] retName, int[] lenTypePos);public native int GetColInfoByName(long conn, String name, int[] lenTypePos);public native int Next(long conn); // 到下一条记录,成功返回1,到记录集结束,则为0,错误返回负数public native int GotoRec(long conn, int recNo); // 记录号从1开始// 取字段值:1.总是返回字符串结果,2.字符串变量要预先分配至少2048大小的长度public native int LxjDbGetValByName(long conn, String fieldName, String[] retVal);// 列编号从0开始public native int GetValByIndex(long conn, int col, String[] retVal);}然后用javah生成c语言的头文件来编译jni,将c文件存放在jni目录下,在终端下使用命令行。

javah -classpath bin -d jni com.lxjdb.jdbc.LxjDbApi

下面是cpp代码,是调用我们的c语言api:

/* DO NOT EDIT THIS FILE – it is machine generated */#include "com_lxjdb_jdbc_LxjDbApi.h"/* Header for class com_lxjdb_jdbc_LxjDbApi */#include "LxjDbApi.h"/* * Class:com_lxjdb_jdbc_LxjDbApi * Method: Open * Signature: (Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)Ljava/lang/Long; */JNIEXPORT jlong JNICALL Java_com_lxjdb_jdbc_LxjDbApi_Open(JNIEnv * env, jobject obj, jstring host, jint port, jstring user, jstring pwd){ LxjDbInit();const char* pHost = env->GetStringUTFChars(host, 0); const char* pUser = env->GetStringUTFChars(user, 0); const char* pPwd = env->GetStringUTFChars(pwd, 0);void* conn = LxjDbOpen(pHost, port, "", pUser, pPwd);env->ReleaseStringUTFChars(host, pHost); env->ReleaseStringUTFChars(pwd, pPwd); env->ReleaseStringUTFChars(user, pUser); return((jlong)conn);}/* * Class:com_lxjdb_jdbc_LxjDbApi * Method: Close * Signature: (Ljava/lang/Long;)Ljava/lang/Long; */JNIEXPORT jint JNICALL Java_com_lxjdb_jdbc_LxjDbApi_Close(JNIEnv * env, jobject obj, jlong conn){ void* pConn = (void*)conn; int ret = LxjDbClose(pConn); return(ret);}/** Class:com_lxjdb_jdbc_LxjDbApi* Method: Exec* Signature: (JLjava/lang/String;[Ljava/lang/String;)I*/JNIEXPORT jint JNICALL Java_com_lxjdb_jdbc_LxjDbApi_Exec(JNIEnv * env, jobject obj, jlong conn, jstring sql, jobjectArray dbInfo){ void* pConn = (void*)conn; const char* pSql = env->GetStringUTFChars(sql, 0); int retCode = 0; char pDbInfo[512]; pDbInfo[0] = '\0';int ret = LxjDbExec(pConn, pSql, retCode, pDbInfo);env->ReleaseStringUTFChars(sql, pSql);env->SetObjectArrayElement(dbInfo, 0, env->NewStringUTF(pDbInfo));return(ret>0 ? retCode : ret);}/** Class:com_lxjdb_jdbc_LxjDbApi* Method: Rows* Signature: (J)I*/JNIEXPORT jint JNICALL Java_com_lxjdb_jdbc_LxjDbApi_Rows(JNIEnv * env, jobject obj, jlong conn){ void* pConn = (void*)conn; return( LxjDbRows(pConn) ); // 总行数}/** Class:com_lxjdb_jdbc_LxjDbApi* Method: Cols* Signature: (J)I*/JNIEXPORT jint JNICALL Java_com_lxjdb_jdbc_LxjDbApi_Cols(JNIEnv * env, jobject obj, jlong conn){ void* pConn = (void*)conn; return(LxjDbCols(pConn)); // 总列数}/** Class:com_lxjdb_jdbc_LxjDbApi* Method: GetColInfoByIndex* Signature: (JI[Ljava/lang/String;[I)I*/JNIEXPORT jint JNICALL Java_com_lxjdb_jdbc_LxjDbApi_GetColInfoByIndex(JNIEnv * env, jobject obj, jlong conn, jint col, jobjectArray retName, jintArray lenTypePos){ void* pConn = (void*)conn;char name[200]; name[0] = '\0'; int len=0; int type=0; int pos=0; int ret = LxjDbGetColInfoByIndex(pConn, col, name, len, type, pos); // 根据列索引(从0开始)找到字段信息env->SetObjectArrayElement(retName, 0, env->NewStringUTF(name)); jint *pArr = env->GetIntArrayElements(lenTypePos, NULL); pArr[0] = len; pArr[1] = type; pArr[2] = pos; env->ReleaseIntArrayElements(lenTypePos, pArr, NULL); return(ret);}/** Class:com_lxjdb_jdbc_LxjDbApi* Method: GetColInfoByName* Signature: (JLjava/lang/String;[I)I*/JNIEXPORT jint JNICALL Java_com_lxjdb_jdbc_LxjDbApi_GetColInfoByName(JNIEnv * env, jobject obj, jlong conn, jstring name, jintArray lenTypePos){ void* pConn = (void*)conn; const char* pName = env->GetStringUTFChars(name, 0); int len = 0; int type = 0; int pos = 0;int ret = LxjDbGetColInfoByName(pConn, pName, len, type, pos);env->ReleaseStringUTFChars(name, pName);jint *pArr = env->GetIntArrayElements(lenTypePos, NULL); pArr[0] = len; pArr[1] = type; pArr[2] = pos; env->ReleaseIntArrayElements(lenTypePos, pArr, NULL); return(ret);}/** Class:com_lxjdb_jdbc_LxjDbApi* Method: Next* Signature: (J)I*/JNIEXPORT jint JNICALL Java_com_lxjdb_jdbc_LxjDbApi_Next(JNIEnv * env, jobject obj, jlong conn){ void* pConn = (void*)conn; return(LxjDbNext(pConn)); // 下一行}/** Class:com_lxjdb_jdbc_LxjDbApi* Method: GotoRec* Signature: (JI)I*/JNIEXPORT jint JNICALL Java_com_lxjdb_jdbc_LxjDbApi_GotoRec(JNIEnv * env, jobject obj, jlong conn, jint recNo){ void* pConn = (void*)conn; return(LxjDbGotoRec(pConn, recNo)); // 到指定行}/** Class:com_lxjdb_jdbc_LxjDbApi* Method: LxjDbGetValByName* Signature: (JLjava/lang/String;[Ljava/lang/String;)I*/JNIEXPORT jint JNICALL Java_com_lxjdb_jdbc_LxjDbApi_LxjDbGetValByName(JNIEnv * env, jobject obj, jlong conn, jstring name, jobjectArray retVal){ void* pConn = (void*)conn; const char* pName = env->GetStringUTFChars(name, 0); char val[2048]; val[0] = '\0';int ret = LxjDbGetValByName(pConn, pName, val);env->ReleaseStringUTFChars(name, pName); env->SetObjectArrayElement(retVal, 0, env->NewStringUTF(val)); return(ret);}/** Class:com_lxjdb_jdbc_LxjDbApi* Method: GetValByIndex* Signature: (JI[Ljava/lang/String;)I*/JNIEXPORT jint JNICALL Java_com_lxjdb_jdbc_LxjDbApi_GetValByIndex(JNIEnv * env, jobject obj, jlong conn, jint col, jobjectArray retVal){ void* pConn = (void*)conn; char val[2048]; val[0] = '\0';int ret = LxjDbGetValByIndex(pConn, col, val);env->SetObjectArrayElement(retVal, 0, env->NewStringUTF(val)); return(ret);}再构造一个makefile:

风景如何,其实并不重要。重要的是,你在我的身边。

我实现的内存数据库JDBC驱动

相关文章:

你感兴趣的文章:

标签云: