我正在实施 DCN 以获取有关插入表中的记录的通知。当我尝试在应用程序内或使用外部脚本插入记录时,它不会在控制台中显示事件。
接下来的代码是我的实现:
package co.app.dcn;
import oracle.jdbc.OracleConnection;
import oracle.jdbc.OracleDriver;
import oracle.jdbc.OracleStatement;
import oracle.jdbc.dcn.DatabaseChangeRegistration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
@Component
public class OracleDCNListener {
@Autowired
private JdbcTemplate jdbcTemplate;
@Value("${spring.datasource.username}")
private String DCN_USER;
@Value("${spring.datasource.password}")
private String DCN_PASSWORD;
@Value("${spring.datasource.url}")
private String DCN_URL;
@PostConstruct
public void initialize() throws SQLException {
var conn = connect();
var prop = new Properties();
prop.setProperty(OracleConnection.DCN_NOTIFY_ROWIDS, "true");
prop.setProperty(OracleConnection.DCN_QUERY_CHANGE_NOTIFICATION, "true");
DatabaseChangeRegistration dcr = conn.registerDatabaseChangeNotification(prop);
try {
DCNListener list = new DCNListener(this);
dcr.addListener(list);
// second step: add objects in the registration:
Statement stmt = conn.createStatement();
// associate the statement with the registration:
((OracleStatement) stmt).setDatabaseChangeRegistration(dcr);
ResultSet rs = stmt.executeQuery("SELECT * FROM CONTRATOS.CON_ESTADOS_PAGOS_CONTRATOS_NOTIFY");
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 {
// Note that we close the connection!
conn.close();
} catch (Exception innerex) {
innerex.printStackTrace();
}
}
synchronized (this) {
// The following code modifies the dept table and commits:
try {
OracleConnection conn2 = connect();
conn2.setAutoCommit(false);
Statement stmt2 = conn2.createStatement();
stmt2.executeUpdate("insert into contratos.CON_ESTADOS_PAGOS_CONTRATOS_NOTIFY (ID, ID_CLASE_DOCUMENTO, NUMERO_DOCUMENTO, OBSERVACIONES, ID_ESTADO, DESCRIPCION_ESTADO, FECHA_HORA_CREACION) values (99999920, 0, 0, ' ', 0, ' ', ' ')",
Statement.RETURN_GENERATED_KEYS);
ResultSet autoGeneratedKey = stmt2.getGeneratedKeys();
if (autoGeneratedKey.next())
System.out.println("inserted one row with ROWID=" + autoGeneratedKey.getString(1));
stmt2.executeUpdate("insert into contratos.CON_ESTADOS_PAGOS_CONTRATOS_NOTIFY (ID, ID_CLASE_DOCUMENTO, NUMERO_DOCUMENTO, OBSERVACIONES, ID_ESTADO, DESCRIPCION_ESTADO, FECHA_HORA_CREACION) values (99999922, 0, 0, ' ', 0, ' ', ' ')",
Statement.RETURN_GENERATED_KEYS);
autoGeneratedKey = stmt2.getGeneratedKeys();
if (autoGeneratedKey.next())
System.out.println("inserted one row with ROWID=" + autoGeneratedKey.getString(1));
stmt2.close();
conn2.commit();
conn2.close();
} catch (SQLException ex) {
ex.printStackTrace();
}
// wait until we get the event
try {
this.wait();
} catch (InterruptedException ie) {
}
}
// At the end: close the registration (comment out these 3 lines in order
// to leave the registration open).
//OracleConnection conn3 = connect();
//conn3.unregisterDatabaseChangeNotification(dcr);
//conn3.close();
}
OracleConnection connect() throws SQLException {
OracleDriver dr = new OracleDriver();
Properties prop = new Properties();
prop.setProperty("user", DCN_USER);
prop.setProperty("password", DCN_PASSWORD);
return (OracleConnection) dr.connect(DCN_URL, prop);
}
}
package co.app.dcn;
import oracle.jdbc.dcn.DatabaseChangeEvent;
import oracle.jdbc.dcn.DatabaseChangeListener;
public class DCNListener implements DatabaseChangeListener {
OracleDCNListener oracleDCNListener;
public DCNListener(OracleDCNListener oracleDCNListener) {
this.oracleDCNListener = oracleDCNListener;
}
public void onDatabaseChangeNotification(DatabaseChangeEvent e)
{
Thread t = Thread.currentThread();
System.out.println("DCNDemoListener: got an event ("+this+" running on thread "+t+")");
System.out.println(e.toString());
synchronized( oracleDCNListener ){ oracleDCNListener.notify();}
}
}
我已经检查了 SELECT * FROM USER_CHANGE_NOTIFICATION_REGS ,是的,正在创建注册记录。
您可以尝试设置以下 DCN 注册属性吗? prop.setProperty(OracleConnection.DCN_CLIENT_INIT_CONNECTION, "true")