java mysql跨库跨表_java实现跨数据库关联运算的简便方法

Java程序开发中会碰到跨数据库关联运算的情况,这里通过一个例子来看Java实现的方法。例子中sales表在db2数据库中,employee表在mysql数据库中。要将sales和employee表通过sales中的sellerid和employee中的eid关联起来,过滤出state=”California”的所有sales和employee数据。

Sales表的结构和数据如下:

076070d176b0287c6a544188a1fca328.png

Employee表的结构和数据如下:

3e2c23c30853c1fefa1d2662896540e9.png

两个表来自不同数据库,没有办法用sql来实现join。这里采用Java的数据计算类库RowSet来实现。RowSet提供了JoinRowSet和FilteredRowSet类,可以进行跨库的计算。

Java程序的编写思路是:

1、分别从db2和mysql数据库中读入sales表和employee表数据,存入CachedRowSet对象中。

2、使用JoinRowSet完成两个表的内连接。

3、使用FilteredRowSet完成条件过滤。

4、打印出结果数据。

下面两个函数分别读入db2和mysql数据,具体的代码如下:

public static RowSet db2() throws Exception {

String drive = "com.ibm.db2.jcc.DB2Driver";

String url = "jdbc:db2://127.0.0.1:50000/demo";

String DBUSER="db2admin";

String password="db2admin";

Connection conn = null;

Statement stmt= null;

ResultSet result = null;

Class.forName(drive);

conn =DriverManager.getConnection(url,DBUSER,password);

stmt = conn.createStatement();

result1 =stmt.executeQuery("SELECT * FROM sales");

CachedRowSetcachedRS = new CachedRowSetImpl();

cachedRS.populate(result);

result.close();

stmt.close();

conn.close();

returncachedRS;

}

public staticRowSetmysql() throws Exception {

Stringdrive = "com.mysql.jdbc.Driver";

String url ="jdbc:mysql://127.0.0.1:3306/test";

String DBUSER="root";

String password="root";

Connection conn = null;

Statement stmt= null;

ResultSet result1 = null;

Class.forName(drive);

conn=DriverManager.getConnection(url,DBUSER,password);

stmt = conn.createStatement();

result1 =stmt.executeQuery("SELECT * FROM employee");

CachedRowSetcachedRS = newCachedRowSetImpl();

cachedRS.populate(result1);

result1.close();

stmt.close();

conn.close();

returncachedRS;

}

下面的函数实现两个表的连接(join)和过滤(filter)。

publicstatic void myJoin() throws Exception {

//从两个数据库中取数

RowSetmysqlRS= mysql();

RowSetdb2RS= db2();

//完成两个表的join

JoinRowSetjoinRS= new JoinRowSetImpl();

joinRS.addRowSet(db2RS,"SELLERID");

joinRS.addRowSet(mysqlRS,"EID");

//完成条件过滤

FilteredRowSetfilterRS= new FilteredRowSetImpl();

filterRS.populate(joinRS);

StateRangerange = new StateRange();//过滤条件,具体实现见后

filterRS.setFilter(range);

while(filterRS.next()){//打印结果

int  ORDERID=filterRS.getInt("ORDERID");

int  SELLERID =filterRS.getInt("SELLERID");

StringNAME = filterRS.getString("NAME");

String STATE =filterRS.getString("STATE");

System.out.print("ORDERID="+ORDERID+";");

System.out.print("SELLERID="+SELLERID+";");

System.out.print("NAME="+NAME+";");

System.out.print("STATE="+STATE+";");

}

}

其中的StateRange对象需要自行实现,例如下面这个内部类:

public staticclass StateRange implements Predicate {

publicStateRange(){}

publicbooleanevaluate(RowSetrs) {

try {

if(rs.getString("STATE").equals("California"))

return true;//如果state等于California则保留

} catch (SQLException e) {

// do nothing

}

return false;

}

publicboolean evaluate(Objectvalue, int column) throws SQLException {

return false;

}

publicboolean evaluate(Objectvalue, String columnName)

throwsSQLException{

return false;

}

}

上面的代码实现了db2和mysql的跨库关联和过滤计算,但是有很多局限。首先是JoinRowSet只支持inner join,不支持outterjoin。第二是db2、mysql和hsql经过测试是可以使用JoinRowSet的,但是oracle 11g和其他数据库关联的的时候虽然不报错,但是结果集为空。如果是oracle11g的两个数据库用户跨库做join,使用JoinRowSet可以得到正确的结果。所以说不同数据库厂家提供的Jdbc实现可能会影响上述方法的结果。第三,就是编程还是有点复杂。

采用集算器esProc辅助会是个更轻松的方案。集算器是专门为结构化(半结构化)数据处理设计的开发语言,实现跨数据库的关联计算很轻松,并和Java程序能无缝结合,从而使Java程序可以象SQL那样灵活实现跨库数据计算。集算器支持各种数据库,包括:oracle、db2、mysql、sqlserver、sybase、postgre等,均可完成inner join和outter join等各种跨库关联运算。

实现上述需求的esProc代码只需要8行,如下:

edd2d13ce5d5be5300a4c36c908b1596.png

A1:连接预先配置好的db2数据源。

A2:连接预先配置好的mysql数据源。实际上对于oracle等其他数据库也同样支持。

A3、A4:分别从db2和mysql中读取sales序表和employee序表。esProc的集成开发环境可以直观的显示出导入的数据,如上图右边部分。

A5:使用集算器的对象引用机制,将sales序表和employee序表通过sellerid=eid关联。

A6:按照state="California"过滤序表。

A7:生成一个新的序表,得到需要的字段。

A8:返回给集算器程序的调用者。

最后,还需要在Java程序中调用这段esProc程序获得结果,使用esProc提供的jdbc即可完成。将上述esProc程序保存为test.dfx文件的话,Java调用的代码如下:

//建立esProcjdbc连接

Class.forName("com.esproc.jdbc.InternalDriver");

con= DriverManager.getConnection("jdbc:esproc:local://");

//调用esProc程序(存储过程),其中test是dfx的文件名

com.esproc.jdbc.InternalCStatementst;

st =(com.esproc.jdbc.InternalCStatement)con.prepareCall("calltest()");

//执行esProc存储过程

st.execute();

//获取结果集

ResultSet set = st.getResultSet();

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值