当插入数量超过 20 时,Oracle 数据库更改通知不起作用

Oracle database change notification not working when inserts qty exceeds 20

public class Register {

    @Autowired
    private DataSource dataSource;

    @Autowired
    private DCNListener listener;


    private OracleConnection oracleConnection = null;
    private DatabaseChangeRegistration dcr = null;
    private Statement statement = null;
    private ResultSet rs = null;


    @PostConstruct
    public void init() {
        this.register();
    }


    private void register() {


        Properties props = new Properties();
        props.put(OracleConnection.DCN_NOTIFY_ROWIDS, "true");
        props.setProperty(OracleConnection.DCN_IGNORE_DELETEOP, "true");
        props.setProperty(OracleConnection.DCN_IGNORE_UPDATEOP, "true");

        try {

            oracleConnection = (OracleConnection) dataSource.getConnection();

            dcr = oracleConnection.registerDatabaseChangeNotification(props);
            statement = oracleConnection.createStatement();
            ((OracleStatement) statement).setDatabaseChangeRegistration(dcr);

            rs = statement.executeQuery(listenerQuery);

            while (rs.next()) {

            }

            dcr.addListener(listener);

            String[] tableNames = dcr.getTables();
            Arrays.stream(tableNames)
                    .forEach(i -> log.debug("Table {}" + " registered.", i));

        } catch (SQLException e) {
            e.printStackTrace();
            close();
        }

    }
}

我的听众:

public class DCNListener implements DatabaseChangeListener {

    @Override
    public void onDatabaseChangeNotification(DatabaseChangeEvent databaseChangeEvent) {

        TableChangeDescription[] tableChanges = databaseChangeEvent.getTableChangeDescription();

        for (TableChangeDescription tableChange : tableChanges) {

            RowChangeDescription[] rcds = tableChange.getRowChangeDescription();

            for (RowChangeDescription rcd : rcds) {

                RowOperation op = rcd.getRowOperation();
                String rowId = rcd.getRowid().stringValue();

                switch (op) {

                    case INSERT:
                        //process
                        break;

                    case UPDATE:
                        //do nothing
                        break;

                    case DELETE:
                       //do nothing
                        break;

                    default:
                        //do nothing
                }

            }

        }
    }
}

在我的 Spring 引导应用程序中,我有一个 Oracle DCN 注册器 class,它在我的数据库的事件 table 中侦听 INSERTS。我正在监听插入新记录。

在这个事件 table 中,我的应用程序支持不同类型的事件,比如 EventA 和 EventB。

应用程序 gui 允许您批量上传这些类型的事件,这些事件转化为 INSERT 到 oracle 数据库中 table 我正在收听。

对于其中一种事件类型,当批量上传 20 个或更多事件时,我的应用程序不会捕获 INSERT ONLY,但对于另一种事件类型,我会没有遇到这个问题。

所以假设用户插入 eventA 任何 < 20 的数字,我的应用程序捕获插入。但是如果eventA插入的次数超过20,则不捕获。

eventB 情况并非如此,它运行顺畅。我想知道我是否遗漏了注册方面的任何内容以及我可以在数据库中查找的任何内容,或者这里可能存在什么问题?

您还应该从以下位置查找 ALL_ROWS 事件:

EnumSet<TableChangeDescription.TableOperation> tableOps = tableChange.getTableOperations();
if(tableOps.contains(TableChangeDescription.TableOperation.ALL_ROWS)){
  // Invalidate the cache
}

引用自 JavaDoc:

当 table 完全无效且行级别信息不可用时,将发送 ALL_ROWS 事件。如果在注册期间未打开 DCN_NOTIFY_ROWIDS 选项,则所有事件都将打开此 OPERATION_ALL_ROWS 标志。它也可能发生在太多行已更改并且服务器发送它们的列表太昂贵的情况下。

https://docs.oracle.com/en/database/oracle/oracle-database/12.2/jajdb/oracle/jdbc/dcn/TableChangeDescription.TableOperation.html#ALL_ROWS