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

来源:互联网 发布:spark java编程实例 编辑:程序博客网 时间:2024/04/30 12:54

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

    Sales表的结构和数据如下:

wKioL1QeO2jD7x2iAAFqEoXflcg692.jpg

    Employee表的结构和数据如下:

wKioL1QeO2mxHfH-AAHvtvrK6zQ085.jpg

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

    Java程序的编写思路是:

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

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

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

    4、  打印出结果数据。

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

    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;

                   }

         }

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

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

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

wKiom1QeO07Q5IF3AAMLsV_4b1M953.jpg

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

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

   A3A4:分别从db2mysql中读取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程序(存储过程),其中testdfx的文件名

com.esproc.jdbc.InternalCStatementst;

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

//执行esProc存储过程

st.execute();

//获取结果集

ResultSet set = st.getResultSet();


0 0
原创粉丝点击