设为首页 加入收藏

TOP

我实现的内存数据库JDBC驱动(一)
2015-07-24 10:56:07 来源: 作者: 【 】 浏览:3
Tags:实现 内存 数据库 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
首页 上一页 1 2 3 4 5 下一页 尾页 1/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇为什么不记录慢查询? 下一篇windows下sqlplus/assysdba报ora-..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·Java 并发工具类:提 (2025-12-25 20:25:44)
·Java面试技巧:如何 (2025-12-25 20:25:41)
·Java并发编程中的线 (2025-12-25 20:25:38)
·C 语言 - cppreferen (2025-12-25 19:50:27)
·《C 语言入门教程》 (2025-12-25 19:50:23)