20 Kasım 2023 Pazartesi

JDBC Reactive

Giriş
Açıklaması şöyle
The JDBC Reactive Extensions are available in the Oracle JDBC Thin Driver 21c or later. The extensions expose standard Java Flow Subscriber and Publisher types and APIs that can interoperate with the R2DBC API and other Reactive Streams libraries.
Jar
Açıklaması şöyle
Interestingly, if you are using the Oracle JDBC Driver, you do not have to include another JAR as a dependency. The JDBC Reactive Extensions belong to the same dependency artefact (JAR file) as the Oracle JDBC Driver.
Tipler
Açıklaması şöyle. Yani JDBC Reactive ile diğer kütüphanelerin beklediği tipler uyuşmuyor
The JDBC Reactive Extensions APIs handle the low-level mechanics of the Flow API to the application using java.util.concurrent.Flow.Publisher and java.util.concurrent.Flow.Subscriber. Popular libraries such as Reactor, RxJava, and Akka-Streams interface with the org.reactivestreams.Publisher and org.reactivestreams.Subscriber types defined by the reactive-streams-jvm project as specified in the following link:
Açıklaması şöyle. Yani JDBC Reactive ile diğer kütüphanelerin beklediği tipler uyuşmuyor
You can convert between the Flow type and the org.reactivestreams type using the org.reactivestreams.FlowAdapters class 
...
Oracle recommends that you use the Reactive Streams libraries when interfacing with the Flow types exposed by the JDBC driver.
API
OraclePreparedStatement  metodları şöyle
Flow.Publisher<Boolean> executeAsyncOracle
Flow.Publisher<Long> executeUpdateAsyncOracle
Flow.Publisher<Long> executeBatchAsyncOracle
Flow.Publisher<OracleResultSet> executeQueryAsyncOracle
Açıklaması şöyle
JDBC Reactive Extensions have the following limitations:

- You must access the asynchronous methods through the java.sql.Wrapper.unwrap method, instead of accessing those through a typecast. This ensures correct behaviour of the asynchronous methods when you use them with proxy Oracle JDBC classes, for example, when you use asynchronous methods with connection pools.
- Reading large responses from the network may require blocking I/O bound operations. Blocking read operations can occur if the driver reads a response that is larger than the TCP Receive buffer size.
- Asynchronous SQL execution supports neither scrollable ResultSet types nor sensitive ResultSet types.

executeAsyncOracle metodu
Örnek - CREATE TABLE
Elimizde şöyle bir kod olsun
import java.sql.SQLException;
import java.util.concurrent.Flow;

import oracle.jdbc.OracleConnection;
import oracle.jdbc.OraclePreparedStatement;
import oracle.jdbc.pool.OracleDataSource;

private OracleDataSource ods = null;
private OracleConnection conn = null;

try {
  OracleDataSource ods = new OracleDataSource();
  // jdbc:oracle:thin@[hostname]:[port]/[DB service/name]
  ods.setURL("jdbc:oracle:thin@[hostname]:[port]/[DB service/name");
  ods.setUser("[Username]");
  ods.setPassword("[Password]");

  conn = (OracleConnection) ods.getConnection();
  // Execute a SQL DDL statement to create a database table asynchronously
  createTable(conn);
} catch (SQLException e) {
 ...
}
Şöyle yaparız
Flow.Publisher<Boolean> createTable(OracleConnection connection)throws SQLException {
  OraclePreparedStatement createTableStatement = (OraclePreparedStatement) 
  connection.prepareStatement("CREATE TABLE employee_names (id NUMBER PRIMARY KEY,"
      + "first_name VARCHAR(50), last_name VARCHAR2(50))");

  Flow.Publisher<Boolean> createTablePublisher = createTableStatement
    .unwrap(OraclePreparedStatement.class)
    .executeAsyncOracle();

  createTablePublisher.subscribe(
    // This subscriber will close the PreparedStatement
    new Flow.Subscriber<Boolean>() {
      @Override
      public void onSubscribe(Flow.Subscription subscription) {
	subscription.request(1L);
      }

      @Override
      public void onNext(Boolean item) {}

      @Override
      public void onError(Throwable throwable) {closeStatement();}

      @Override
      public void onComplete() {closeStatement();}

      void closeStatement() {
	try {
	  createTableStatement.close();
	} catch (SQLException closeException) {
	}
      }
  });
  return createTablePublisher;
}
executeUpdateAsyncOracle metodu
Örnek
Şöyle yaparız
class PipelineExample{
  void pipelineExample(OracleConnection connection) throws SQLException {
    PreparedStatement delete = connection.prepareStatement(
            "DELETE FROM example WHERE id = 0");
    PreparedStatement insert = connection.prepareStatement(
            "INSERT INTO example (id, value) VALUES (1, 'x')");
    PreparedStatement select = connection.prepareStatement(
            "SELECT id, value FROM example WHERE id = 2");

    Flow.Publisher<Long> deletePublisher =
            delete.unwrap(OraclePreparedStatement.class).executeUpdateAsyncOracle();
    Flow.Publisher<Long> insertPublisher =
            insert.unwrap(OraclePreparedStatement.class).executeUpdateAsyncOracle();
    Flow.Publisher<OracleResultSet> selectPublisher =
            select.unwrap(OraclePreparedStatement.class).executeQueryAsyncOracle();

    // Subscribe to publishers to get results back
    …
  }
}
Örnek
Şöyle yaparız. Burada org.reactivestreams.FlowAdapters.toPublisher() kullanılıyor
// Execute statements in a pipeline
Flow.Publisher<Long> deletePublisher =
  delete.unwrap(OraclePreparedStatement.class).executeUpdateAsyncOracle();
Flow.Publisher<Long> insertPublisher =
  insert.unwrap(OraclePreparedStatement.class).executeUpdateAsyncOracle();
Flow.Publisher<OracleResultSet> selectPublisher =
  select.unwrap(OraclePreparedStatement.class).executeQueryAsyncOracle();

// Consume statement results synchronously with Project Reactor
long deleteCount = Mono.from(toPublisher(deletePublisher)).block();
System.out.println(deleteCount + " rows deleted");

long insertCount = Mono.from(toPublisher(insertPublisher)).block();
System.out.println(insertCount + " rows inserted");

OracleResultSet resultSet = Mono.from(toPublisher(selectPublisher)).block();



9 Kasım 2023 Perşembe

DUAL Sistem Tablosu

Örnek
Şöyle yaparız
SELECT 'Hello World!' FROM dual;

Docker ve Oracle

Örnek - 23c
Şöyle yaparız
docker pull gvenzl/oracle-free

docker run -d \
  -p 1521:1521 \
  -e ORACLE_PASSWORD=<your password> \
  -v oracle-volume:/opt/oracle/oradata \
  gvenzl/oracle-free
XE ve Slim
Oracle Database Express Edition (Oracle Database XE) anlamına gelir. Oracle Application Express (APEX) araçlarını içermez

Örnek
Şöyle yaparız. Kullanıcı adı system şifre mypassword  olur
docker run -d -p 1521:1521 -e ORACLE_PASSWORD=mypassword gvenzl/oracle-xe:21-slim-faststart