Tutorial: Learn how to implement data change notifications in the Oracle Database! 🤔

Receiving database change notifications is a powerful concept when it comes to software development and relational database dev projects and in this tutorial, we’ll explore an Oracle database change notification (Oracle DCN) Java code example.

Oracle Change Notification TOC

Oracle Continuous Query Notification (Oracle CQN) is a real-time event notification feature in the Oracle Database (see also: the Oracle Database page on Wikipedia) that allows applications to receive immediate notifications when defined relational database modifications take place, enabling timely responses as well as push-based data synchronization.

In this instructional, we’ll detail the steps required to configure Oracle change notification events via the JDBC driver.

This article was updated on May 27, 2025 — note that this guide also appears as an advanced example in the Introduction to Java article.

Preconditions to running the Oracle change notification Java example

The following two gists are required preconditions for this example.

It is important to note that Docker was running on another machine which, in this case, uses the Ubuntu operating system.

See the warning regarding running Oracle in Docker locally in the DatabaseChangeListenerInOracleDatabaseExample.groovy script for complete details (find the gist on GitHub).

				
					#
# In this example Docker is running on another machine so assume that I've ssh'd into that box and
# am running the following on the remote machine.
#
docker run -d -p 1521:1521 oracleinanutshell/oracle-xe-11g
docker exec -it [container id] /bin/sh
su
#
# Username: system, password: oracle
#
/u01/app/oracle/product/11.2.0/xe/bin/sqlplus
				
			

In SQL*Plus, we can now run the following configuration script.

Keep in mind that once the example table has been created, see line #8, the Groovy script in the next section can be started and any insert, update, or delete operations on the target table will result in an event being sent to the Groovy script and then printed to the console output (find the gist on GitHub).

				
					--
-- This is required otherwise notifications won't be sent to the JDBC driver.
--
grant change notification to system;

commit;

CREATE TABLE example(
  example_id NUMBER(10) PRIMARY KEY,
  phrase VARCHAR2(120) NOT NULL
);

commit;

insert into example values (1, 'one');
insert into example values (2, 'two');
insert into example values (3, 'three');
insert into example values (4, 'four');
insert into example values (5, 'five');
commit;

--
-- Then once the DatabaseChangeListenerInOracleDatabaseExample.groovy is running
-- execute the following and an update should appear in the Groovy console:
--
update example set phrase = 'one / 1' where example_id = 1;
				
			

In the next section we’ll explore the steps required to code an Oracle change notification example in the Java programming language (see also: the Java programming language page on Wikipedia).

How to implement the DatabaseChangeListener Java Example callback

Here we’ll provide step-by-step instructions for implementing the oracle.jdbc.dcn.DatabaseChangeListener callback using the Groovy scripting language, which extends the Java programming language and comes in handy for building and running short examples, like what we have here.

Step One: Implement Preconditions

For this example, we’ll need to include the com.oracle.database.jdbc ojdbc6 dependency version 11.2.0.4.

If you run this example via the groovyConsole and Groovy Grape should be able to pull in the dependency without any additional steps required.

Step Two: Import the required classes

We need to import the Oracle DatabaseChangeListener callback along with other supporting classes required to run this example.

				
					import oracle.jdbc.dcn.DatabaseChangeListener
import oracle.jdbc.dcn.DatabaseChangeEvent
import oracle.jdbc.driver.OracleConnection
import oracle.jdbc.dcn.DatabaseChangeRegistration
import oracle.jdbc.OracleStatement

import java.sql.DriverManager

import java.util.Properties
				
			

Step Three: Get a connection to the Oracle Database using the Oracle JDBC driver manager

We need to get a connection from the Oracle JDBC driver manager — in this example, the endpoint we’re using is running locally in Docker.

				
					final def connection = DriverManager.getConnection("jdbc:oracle:thin:@192.168.1.232:1521:xe", "system", "oracle")
				
			

Step Four: Get an instance of DatabaseChangeRegistration

We need to set some properties and then get an instance of DatabaseChangeRegistration from the connection to the Oracle relational database.

				
					databaseProperties.setProperty(OracleConnection.DCN_NOTIFY_ROWIDS, "true")
databaseProperties.setProperty(OracleConnection.DCN_QUERY_CHANGE_NOTIFICATION, "true")

final def databaseChangeRegistration = connection.registerDatabaseChangeNotification(databaseProperties)
				
			

Step Five: Implement the Oracle DatabaseChangeListener interface.

Implement the Oracle oracle.jdbc.dcn.DatabaseChangeListener interface.

In this example, we’re simply printing out some of the information included in the oracle.jdbc.dcn.DataChangeEvent parameter, as is demonstrated below.

				
					public class ExampleDatabaseChangeListener implements DatabaseChangeListener {

    @Override
    public void onDatabaseChangeNotification(DatabaseChangeEvent databaseChangeEvent) {
        println ("***** databaseChangeEvent: $databaseChangeEvent")
        println ("***** databaseChangeEvent.source: ${databaseChangeEvent.source}")
        println ("***** databaseChangeEvent.queryChangeDescription: ${databaseChangeEvent.queryChangeDescription}")
        println ("***** databaseChangeEvent.tableChangeDescription: ${databaseChangeEvent.tableChangeDescription.each {println '\n  - nextTableChangeDescription: $it' } }")
    }
}
				
			

Step Six: Register a new instance of the example DatabaseChanceListener with the instance of DatabaseChangeRegistration.

In this step we need to register a new instance of the ExampleDatabaseChangeListener, which is an instance of  oracle.jdbc.dcn.DatabaseChangeListener with the instance of oracle.jdbc.dcn.DatabaseChangeRegistration.

				
					databaseChangeRegistration.addListener(new ExampleDatabaseChangeListener ())
				
			

Step Seven: Assign the DatabaseChangeRegistration instance to the statement

We need to create a statement and then register a new instance of DatabaseChangeRegistration with that statement by calling the setDatabaseChangeRegistration method.

				
					final def statement = connection.createStatement()

statement.setDatabaseChangeRegistration(databaseChangeRegistration)
				
			

Oracle Database Change Notification Full Example

Here we have an example of the complete DatabaseChangeListenerInOracleDatabaseExample.groovy script.

Groovy is an excellent scripting language that extends the Java programming language and we’ll try to stay close to Java as our approach to building out the code below.

Note that the developer must implement one method:

void onDatabaseChangeNotification(DatabaseChangeEvent databaseChangeEvent)

We can see this implementation on line #55 below (find the gist on GitHub).

				
					@GrabConfig(systemClassLoader=true)

@Grapes(
    @Grab(group='com.oracle.database.jdbc', module='ojdbc6', version='11.2.0.4')
)
import oracle.jdbc.dcn.DatabaseChangeListener
import oracle.jdbc.dcn.DatabaseChangeEvent
import oracle.jdbc.driver.OracleConnection
import oracle.jdbc.dcn.DatabaseChangeRegistration
import oracle.jdbc.OracleStatement

import java.sql.DriverManager

import java.util.Properties

final def connection = DriverManager.getConnection("jdbc:oracle:thin:@192.168.1.232:1521:xe", "system", "oracle")

def databaseProperties = new Properties ()

databaseProperties.setProperty(OracleConnection.DCN_NOTIFY_ROWIDS, "true")
databaseProperties.setProperty(OracleConnection.DCN_QUERY_CHANGE_NOTIFICATION, "true")

final def databaseChangeRegistration = connection.registerDatabaseChangeNotification(databaseProperties)

public class ExampleDatabaseChangeListener implements DatabaseChangeListener {

    @Override
    public void onDatabaseChangeNotification(DatabaseChangeEvent databaseChangeEvent) {
        println ("***** databaseChangeEvent: $databaseChangeEvent")
        println ("***** databaseChangeEvent.source: ${databaseChangeEvent.source}")
        println ("***** databaseChangeEvent.queryChangeDescription: ${databaseChangeEvent.queryChangeDescription}")
        println ("***** databaseChangeEvent.tableChangeDescription: ${databaseChangeEvent.tableChangeDescription.each {println '\n  - nextTableChangeDescription: $it' } }")
    }
}

databaseChangeRegistration.addListener(new ExampleDatabaseChangeListener ())

final def statement = connection.createStatement()

statement.setDatabaseChangeRegistration(databaseChangeRegistration)

try {

  resultSet = statement.executeQuery("select * from example")

  while (resultSet.next())
    {} // println "resultSet.phrase: ${resultSet.getString('phrase')}"

} catch (Throwable thrown) {
  thrown.printStackTrace (System.err)
}

println "databaseChangeRegistration.userName: ${databaseChangeRegistration.userName}"

databaseChangeRegistration.tables.each {
    println "tables: $it"
}

final def time = 60 * 60 * 1000

println "Will sleep for $time milliseconds..."

try {
  Thread.sleep (time)
} catch (Throwable thrown) {
  thrown.printStackTrace (System.err)
} finally {
  statement.close ()
  connection.close ()
}

println "...done!"
				
			

The following image goes into deeper detail regarding what each step is doing, along with some notes explaining the output.

An explanation of the example script used to implement the Oracle DCN logic in Groovy with pointers as follows: 1.) Acquire and instance of DatabaseChangeRegistration from the JDBC connection 2.) Implement the DatabaseChangeListener interface 3.) Register the implementation created in the previous step with the databaseChangeRegistration 4.) Register the databaseChangeRegistration with the statement and 5.) Execute a query against the table we're expecting the data change notifications to be sent from.
An explanation regarding how to implement Data Change Notification in the Oracle DB (Oracle DCN).

Lastly, the following image demonstrates that when we perform five inserts in a row and then commit the changes, only a single event is emitted, which includes these five inserts. Events are only ever emitted whenever a commit has returned successfully.

Example Groovy Console output for the change notification example using the Oracle Database where we can see five inserts that were executed in SQL*Plus followed by a single commit -- in the output, we can see that the operation is INSERT along with the row id.
Five inserts are executed in SQL*Plus followed by a single commit and we can see that this event includes these five insert operations.

In the next section we’ll take a look at some of the details regarding custom callback handling as it pertains to the oracle.jdbc.dcn.DatabaseChangeListener interface.

Custom callback handling with the oracle.jdbc.dcn.DatabaseChangeListener specification

The oracle.jdbc.dcn.DatabaseChangeListener callback specification is an interface defined in the Oracle JDBC (Java Database Connectivity) library used in Java applications to implement database change notification functionality in the Oracle Database.

Key components when implementing custom callback handling include:

Oracle Database Change Notification (DCN)

Oracle Database Change Notification feature allows applications to receive real-time notifications when certain database events or changes in the database take place.

These events include data modifications such as insert, update, and delete operations, changes in database objects, or other specified events.

Oracle Database Change Notification Callback

In the context of the Oracle JDBC library, the oracle.jdbc.dcn.DatabaseChangeListener is a Java interface provided by Oracle.

The DatabaseChangeListener specification serves as a blueprint for creating callback objects that can be registered with the relational database to handle change notifications.

Software engineers can implement this interface and define custom logic that will execute when a database change event takes place.

The DatabaseChangeListener specification contains a single method, onDatabaseChangeNotification, that must be implemented by the developer to handle specific database change events.

When a registered change event matches the conditions set by the application, the corresponding callback method is invoked, allowing the application to respond to the event in a custom way.

In summary, the oracle.jdbc.dcn.DatabaseChangeListener callback is part of the Oracle JDBC library and is used to implement custom callback logic for handling Oracle Database Change Notification events.

Software developers create classes that implement this interface to define how their Java applications should respond to real-time database changes.

The DatabaseChangeListener callback allows applications to stay updated and take immediate action when relevant database events occur.

Tutorial Conclusion

In conclusion, Oracle Database change notification updates offer a powerful way to monitor database changes in real time, improving efficiency and enabling proactive responses to critical updates.

Intercepting Oracle DCN events can help to optimize database management as well as streamline operations across enterprise environments.

Learn more about database change notifications — a hidden gem supported by some relational databases.

See Also

author avatar
ThosPFuller
I am a software engineer based in Northern Virginia (USA) and this website focuses on content engineering, web development, Technical SEO, Search Engine Optimization (SEO).

Leave a Reply