ICE专题:JDBC桥接器

本文涉及的产品
云原生数据库 PolarDB MySQL 版,Serverless 5000PCU 100GB
简介:

曾几何时在linux编c语言的时候就会碰到数据库连接的难题,虽然用ODBC可以解决一些问题,但最新的数据库支持必须用JDBC或专用接口才行,而且如ORACLE这种数据库,要想实现远程连接的话,必须安装客户端,对软件的发行产生了一定难度。而JDBC就没有这问题,只要有相关的JDBC驱动就可以正常使用,对软件的成本控制起了一定的积极作用。它很像网络中的桥接器的功能,所以我管它叫JDBC桥接器。

ICE的出现使得这个问题得到了简化,至少不用去关心网络控制和客户端的程序实现语言,只要服务端与客户端用的都是ICE的协议,这个问题就很好解决。下面就这个问题的实现做进一步的讨论。

060606161418.jpg

这个JDBC桥接器的作用是:接受各种数据请求,并通过相应的JDBC数据库驱动连接数据库,并把请求结果返回到客户端。不管这个客户端是在本地还是在网络中,数据库在本地还是在网络中,都可能实现数据的透明传输与应用。

首先我们要做的是,必须在JDBC桥接器所在的机器上开放一个端口,用来接受服务,客户端利用ICE协议向服务端发送请求,并取回操作结果。

有人说,你用的着这么麻烦嘛?用JAVA直接开发客户端不就行了吗?

这个想法应该在很多人心中存在,一个JAVA应用程序的安装也是很烦琐,除非你是BS结构的。这种只能用在JAVA语言身上,但如果我用c/c++开发了一个客户端,只是想用jdbc来操作数据库的话,上面的想法就没有可能实现。并且在跨平台和操作系统的的环境中开发客户端和服务端是一件头痛的事情。

有人说,你要是使用WebService不也可能达到这样的效果吗?请看<<网络服务平台的比较----ICE应用系列文章之一>>,在whhif.cublog.cn可以找到。

在以上环境中,ICE可以避免以上这种种问题。

首先要开发一个slice脚本来定义服务。

module jdbcAgent

{

["java:type:java.util.ArrayList"] sequence <string> row;

["java:type:java.util.ArrayList"] sequence <row> table;

interface Operator

{

int connectDB(string driver,string disp,string host,string port,string db,string name,string pass);

bool insertSQL(string sql);

bool updateSQL(string sql);

bool deleteSQL(string sql);

table querySQL(string sql);

bool closeDB();

};

};

在windows下利用slice2java.exe jdbcAgent.ice生成服务。Linux下利用slice2java jdbcAgent.ice来生成服务。

定义服务的具体内容:

下面的函数与jdbcAgent.ice中所描述的服务是一样的,只是这里给出的是具体实现。只是几个数据库连接的常用功能,编缉ICE所生成的JAVA代码,最好使用eclipse,很方便。并没有定义异常。如果要了解具体实现意义,最好参考ICE的中文白皮书和我写的上一篇入门文章《一个简单的聊天室的实现----ICE应用系列文章之四》,在http://whhif.cublog.cn可以找到。

package jdbcProxy;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.SQLException;

import java.sql.Statement;

import java.sql.ResultSet;

import java.sql.ResultSetMetaData;

import java.util.ArrayList;

import Ice.*;

import jdbcProxy.jdbcAgent.*;

public class jdbcAgentI extends _OperatorDisp {

public static ArrayList m_conn_list;

jdbcAgentI()

{

m_conn_list=new ArrayList();

}

public int connectDB(String driver,String disp,String host,String port,String db,String name,String pass,Current cur)

{

try {

Class.forName(driver);

} catch (ClassNotFoundException cnfe) {

return -1;

}

Connection c = null;

try {

String _disp="jdbc:"+disp+"://"+host+":"+port+"/"+db;

c = DriverManager.getConnection(_disp,name,pass);

} catch (SQLException se) {

return -1;

}

if(c==null)

return -1;

m_conn_list.add(c);

return m_conn_list.size()-1;

}

public boolean insertSQL(String sql,Current cur)

{

Statement s = null;

if(cur.ctx.containsKey("connection_index"))

{

int index = Integer.parseInt((String)cur.ctx.get("connection_index"));

Connection c=(Connection)m_conn_list.get(index);

try {

s = c.createStatement();

} catch (SQLException se) {

return false;

}

try {

s.executeUpdate(sql);

} catch (SQLException se) {

try {

s.close();

} catch (SQLException e) {

return false;

}

return false;

}

try {

s.close();

} catch (SQLException e) {

return false;

}

return true;

}

else

{

return false;

}

}

public boolean updateSQL(String sql,Current cur)

{

Statement s = null;

if(cur.ctx.containsKey("connection_index"))

{

int index = Integer.parseInt((String)cur.ctx.get("connection_index"));

Connection c=(Connection)m_conn_list.get(index);

try {

c.setAutoCommit(true);

s = c.createStatement();

} catch (SQLException se) {

return false;

}

try {

s.executeUpdate(sql);

} catch (SQLException se) {

try {

s.close();

} catch (SQLException e) {

return false;

}

return false;

}

try {

s.close();

} catch (SQLException e) {

return false;

}

return true;

}

else

{

return false;

}

}

public boolean deleteSQL(String sql,Current cur)

{

Statement s = null;

if(cur.ctx.containsKey("connection_index"))

{

int index = Integer.parseInt((String)cur.ctx.get("connection_index"));

Connection c=(Connection)m_conn_list.get(index);

try {

s = c.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);

} catch (SQLException se) {

return false;

}

try {

s.executeUpdate(sql);

} catch (SQLException se) {

try {

s.close();

} catch (SQLException e) {

return false;

}

return false;

}

try {

s.close();

} catch (SQLException e) {

return false;

}

return true;

}

else

{

return false;

}

}

public ArrayList querySQL(String sql,Current cur)

{

Statement s = null;

ArrayList ret=new ArrayList();

if(cur.ctx.containsKey("connection_index"))

{

int index = Integer.parseInt((String)cur.ctx.get("connection_index"));

Connection c=(Connection)m_conn_list.get(index);

ResultSet rs = null;

try {

s = c.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);

} catch (SQLException se) {

return null;

}

try {

rs = s.executeQuery(sql);

} catch (SQLException se) {

try {

s.close();

} catch (SQLException e) {

return null;

}

return null;

}

try {

while (rs.next()) {

ResultSetMetaData rsmd=rs.getMetaData();

int col=rsmd.getColumnCount();

ArrayList tmp=new ArrayList();

for(int i=1;i<=col;++i)

{

tmp.add(rs.getString(i));

}

ret.add(tmp);

}

} catch (SQLException se) {

se.printStackTrace();

try {

s.close();

} catch (SQLException e) {

return null;

}

return null;

}

try {

s.close();

} catch (SQLException e) {

return null;

}

return ret;

}

else

return null;

}

public boolean closeDB(Current cur)

{

int index;

if(cur.ctx.containsKey("connection_index"))

{

index = Integer.parseInt((String)cur.ctx.get("connection_index"));

Connection c=(Connection)m_conn_list.get(index);

try{

if(c!=null)

{

c.close();

}

m_conn_list.remove(index);

return true;

}

catch(SQLException se)

{

return false;

}

}

return true;

}

}

服务实现完成之后,开始写服务端的代码server.java

服务端的代码实现起来非常简单,主要是绑口和加入ICE服务。

package jdbcProxy;

import Ice.*;

public class server extends Application {

public int run(String[] args)

{

ObjectAdapter adapter=communicator().createObjectAdapter("jdbcAgent");

adapter.add(new jdbcAgentI(),Util.stringToIdentity("operator"));

adapter.activate();

communicator().waitForShutdown();

return 0;

}

public static void main(String[] args)

{

server app=new server();

System.exit(app.main("server",args,"config"));

}

}

这样服务器端的代码就完成了,可以运行并等待请求过来。

下面开发两种语言的客户端java和c++的:

有心人可能看出,这两种语言的实现是非常相似的,可以说写出一种,就可以写其它各种语言的客户端,用在不同的需求之中。而且另人振奋的是,不同语言的客户端是可以同时对一个服务端发起请求的,服务器看不到程序语言的差别。

Java语言客户端

package jdbcProxy;

import java.util.HashMap;

import Ice.*;

import java.util.*;

import jdbcProxy.jdbcAgent.OperatorPrx;

import jdbcProxy.jdbcAgent.OperatorPrxHelper;

public class client extends Application {

public int run(String[] args)

{

Ice.Properties properties = communicator().getProperties();

final String proxyProperty = "jdbcAgent.Proxy";

String proxy = properties.getProperty(proxyProperty);

if(proxy.length() == 0)

{

System.err.println("property `" + proxyProperty + "' not set");

return 1;

}

OperatorPrx jaix=OperatorPrxHelper.checkedCast(communicator().stringToProxy(proxy));

int i=jaix.connectDB("org.postgresql.Driver","postgresql","192.168.30.20","5432","test","root","123456");

HashMap ctx=new HashMap();

ctx.put("connection_index",String.valueOf(i));

ArrayList ret=jaix.querySQL("select * from mytable",ctx);

if(ret==null)

return 0;

for(int j=0;j<ret.size();++j)

{

ArrayList tmp=(ArrayList)(ret.get(j));

for(int k=0;k<tmp.size();++k)

System.out.print(tmp.get(k)+" ");

System.out.println();

}

jaix.closeDB(ctx);

return 0;

}

public static void main(String[] args)

{

client app=new client();

System.exit(app.main("client",args,"config"));

}

}

C++语言客户端

#include "globe.h"

class Client : public Application

{

public:

virtual int run(int argc,char * argv[]);

Client();

~Client();

int index;

};

Client::Client()

{

index=-1;

}

Client::~Client()

{

}

int Client::run(int argc,char * argv[])

{

PropertiesPtr properties = communicator()->getProperties();

const char * buf="jdbcAgent.Proxy";

string proxy=properties->getProperty(buf);

if(proxy.empty())

{

cerr << argv[0] << ": property `" << buf << "' not set" << endl;

return EXIT_FAILURE;

}

cout<<proxy<<endl;

OperatorPrx jaix=OperatorPrx::checkedCast(communicator()->stringToProxy(proxy));

if(jaix==0)

{

cout<<"cannot get proxy===================="<<endl;

return 0;

}

Context ctx;

int i=jaix->connectDB("org.postgresql.Driver","postgresql","127.0.0.1","5432","test","root","123456");

if(i==-1)

{

cout<<"Cannot connect the db"<<endl;

return -1;

}

char buf2[20];

sprintf(buf2,"%d",i);

ctx["connection_index"]=buf2;

jaix=OperatorPrx::checkedCast(jaix->ice_newContext(ctx));

for(int i=0;i<10000;++i)

jaix->insertSQL("insert into mytable values('好人啊',100)");

table t=jaix->querySQL("select * from mytable");

for(table::iterator p=t.begin();p!=t.end();++p)

{

CString buf=q->c_str();

ConvertUtf8ToGBK(buf);

string buf2=buf;

cout<<buf2<<" ";

}

jaix->closeDB();

return 0;

}

int main(int argc,char * argv[])

{

Client app;

return app.main(argc,argv,"config");

}

只需要开发这两种客户端的逻辑代码,而不用重新开发服务的接口实现。




本文转自斯克迪亚博客园博客,原文链接:http://www.cnblogs.com/sgsoft/archive/2007/05/03/735225.html,如需转载请自行联系原作者

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
7月前
|
SQL Java 数据库连接
JDBC处理器StatementHandler
回顾MyBatis的执行流程 MyBatis是一个基于JDBC的Dao框架,但前面我们提到的会话、执行器完全没有提到JDBC,原因是MyBatis把所有跟JDBC相关的操作全部都放到了StatementHandler中。 一个SQL请求会经过会话,然后是执行器,最由StatementHandler执行JDBC最终到达数据库。其关系如下图: 注意:我们前面说过在一次会话中SqlSession、Executer、StatementHandler的比例是1:1:N(这里的N取决于通过会话调用了多少次Sql)。即使在可重用执行器的情况下这个比例也是成立的,因为我们只要执行一次SQL就会对应一个
26 0
|
12月前
|
SQL Java 关系型数据库
JDBC驱动接口
JDBC驱动接口
96 0
|
SQL 网络协议 Oracle
【JDBC】JDBC快速入门
1.概述 JDBC是Java DataBase Connectivity的缩写,它是Java程序访问数据库的标准接口。 使用Java程序访问数据库时,Java代码并不是直接通过TCP连接去访问数据库,而是通过JDBC接口来访问,而JDBC接口则通过JDBC驱动来实现真正对数据库的访问。 例如,我们在Java代码中如果要访问MySQL,那么必须编写代码操作JDBC接口。注意到JDBC接口是Java标准库自带的,所以可以直接编译。而具体的JDBC驱动是由数据库厂商提供的,例如,MySQL的JDBC驱动由Oracle提供。因此,访问某个具体的数据库,我们只需要引入该厂商提供的JDBC驱动,就可以通过
148 0
【JDBC】JDBC快速入门
|
Java 数据库连接 数据库
SQLite三种JDBC驱动的区别
在DBeaver中看到SQLite有三种JDBC驱动,查了它们官方网站的相关解释,发现它们还是挺不一样的。   SQLite Wrapper by Christian http://www.ch-werner.de/javasqlite/ 这个驱动其实是在本地C/C++的SQLite上用JDBC实现进行了包装。
1460 0
|
安全 Java 数据库连接
jdbc&nbsp;注册驱动的三种方式
jdbc&nbsp;注册驱动的三种方式
247 0
|
MySQL 关系型数据库 Java
离线安装jdbc driver
maven下载mysql jdbc driver地址https://mvnrepository.com/artifact/mysql/mysql-connector-java/8.0.16
1103 0
|
关系型数据库 Java 数据库连接
|
自然语言处理 Java C++
|
存储 C# 数据库