JAVA结合Oracle的Database Change Notification实现替代获取实时数据需要的刷库操作

本文的编写目的是建立在这个一个需求基础上:某个系统需要不停的读取数据库中的数据来保证系统中展示的数据为最新的实时数据,并且系统的数据库Oracle10.2以上的版本
Database Change Notification的官方资料可以参考https://docs.oracle.com/cd/E11882_01/java.112/e16548/dbchgnf.htm#JJDBC28815


一、首先我们创建一个表做测试用
create table nj_tmp_tmp(id number, val number);


insert into nj_tmp_tmp values(1,100);
insert into nj_tmp_tmp values(2,200);
insert into nj_tmp_tmp values(3,300);
commit;

二、给操作该表的数据库赋予相应的权限
grant change notification to scott;

此处scott仅作示例用,按照实际用户为准
三、编写相应的java代码


oracle官方给出的步骤


简单的翻译就是第一步创建一个注册器,如下所示
 
DatabaseChangeRegistration dcr = conn.registerDatabaseChangeNotification(prop);

其中conn为OracleConnection的实例对象,prop为一些连接的参数
第二步就是写一个查询表示要监听那些表的修改通知,如下所示
statement.executeQuery("select * from nj_tmp_tmp");

此处表示监听nj_tmp_tmp表
第三步就是注册事件,进行绑定,创建notification来用于响应表或者结果集的变动,Oracle数据库使用JDBC驱动通过一个特定网络来通知java事件
 
 dcr.addListener(new DatabaseChangeListener(){




    		@Override
    		public void onDatabaseChangeNotification(DatabaseChangeEvent arg0) {
    			TableChangeDescription[] td=arg0.getTableChangeDescription();
    			  for(TableChangeDescription t:td){
    			        for(RowChangeDescription r:t.getRowChangeDescription()){
    			         ROWID rowid = r.getRowid();
    			         System.out.println("--------"+new String(rowid.getBytes()));
    			        }
    			       }
    		}
        	  
          });



接下来上完整代码:代码参考了oracle官网的资料及网络大牛的各种资料,该 代码中仅对插入事件进行监听
public class DBChangeNotification
{
  static final String USERNAME= "*****";//数据库用户名
  static final String PASSWORD= "*****";//数据库密码
  static String URL;
  
  public static void main(String[] argv)
  {
    URL = "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=127.0.0.1)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=orcl)))";
    try
    {
        OracleConnection conn = connect();
        Properties prop = new Properties();
        prop.setProperty(OracleConnection.DCN_NOTIFY_ROWIDS,"true");
        prop.setProperty(OracleConnection.NTF_TIMEOUT, "0");
        prop.setProperty(OracleConnection.DCN_IGNORE_DELETEOP, "true");
        prop.setProperty(OracleConnection.DCN_IGNORE_UPDATEOP,"true");
        DatabaseChangeRegistration dcr = conn.registerDatabaseChangeNotification(prop);
     
        try
        {
          dcr.addListener(new DatabaseChangeListener(){


    		@Override
    		public void onDatabaseChangeNotification(DatabaseChangeEvent arg0) {
    			TableChangeDescription[] td=arg0.getTableChangeDescription();
    			  for(TableChangeDescription t:td){
    			        for(RowChangeDescription r:t.getRowChangeDescription()){
    			         ROWID rowid = r.getRowid();
    			         System.out.println("--------"+new String(rowid.getBytes()));
    			        }
    			       }
    		}
        	  
          });
          Statement stmt = conn.createStatement();
          ((OracleStatement)stmt).setDatabaseChangeRegistration(dcr);
          ResultSet rs = stmt.executeQuery("select * from nj_tmp_tmp");
          String[] tableNames = dcr.getTables();
          for(int i=0;i<tableNames.length;i++)
            System.out.println(tableNames[i]+" is part of the registration.");
          rs.close();
          stmt.close();
        }
        catch(SQLException ex)
        {
          if(conn != null)
            conn.unregisterDatabaseChangeNotification(dcr);
          throw ex;
        }
        finally
        {
          try
          {
            conn.close();
          }
          catch(Exception innerex){ innerex.printStackTrace(); }
        }
    }
    catch(SQLException mainSQLException )
    {
      mainSQLException.printStackTrace();
    }
  }
 
  /**
   * Creates a connection the database.
   */
  static OracleConnection connect() throws SQLException
  {
    OracleDriver dr = new OracleDriver();
    Properties prop = new Properties();
    prop.setProperty("user",DBChangeNotification.USERNAME);
    prop.setProperty("password",DBChangeNotification.PASSWORD);
    return (OracleConnection)dr.connect(DBChangeNotification.URL,prop);
  }
}










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

L若儿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值