JDBC Type Scroll Нечувствительный и чувствительный - PullRequest
0 голосов
/ 06 февраля 2019

При работе с типами Java JDBC ResultSet есть два типа прокрутки: TYPE_SCROLL_SENSITIVE и TYPE_SCROLL_INSENSITIVE, которые я понял.Но когда я приступил к практической реализации, я не увидел эффекта.Ниже приведен код:

package com.jdbc.resultsettypeandconcurrency;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class TypeInSensitiveConcurUpdate {

    public static void main(String[] args) {
        Connection con = null;
        Statement stmt = null;

        try {
            System.out.println("loading the driver.....");
            Class.forName("oracle.jdbc.driver.OracleDriver");
            System.out.println("Driver loaded");
            con = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl", "user", "pass");
            if(con!=null) {
                System.out.println("Connected to database");

            } else {
                System.out.println("Could not Get Connection");
            }

            stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
            String query = "select COF_NAME, SUP_ID, PRICE, SALES, TOTAL from COFFEES";
            ResultSet rs = stmt.executeQuery(query);
            System.out.println();
            int cnt = 1;
            while(rs.next()) {
                System.out.print(rs.getString("COF_NAME")+", ");
                System.out.print(rs.getInt("SUP_ID")+", ");
                System.out.print(rs.getFloat("PRICE")+", ");
                System.out.print(rs.getInt("SALES")+", ");
                System.out.print(rs.getInt("TOTAL")+"\n");
                if(cnt == 2){
                    try {
                        Thread.sleep(20 * 1000);/**LINE:39*/
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                cnt++;
            }
            System.out.println();

        } catch(ClassNotFoundException e) {
            System.out.println("ClassNotFoundException : Driver Class not found");
            System.out.println(e.getMessage());

        } catch(SQLException e) {
            System.out.println("SQL Error "+e.getMessage());
            System.out.println(e.getErrorCode());

        } finally {
            if(stmt!=null) {
               stmt.close();
            }
            if(con!=null) {
               con.close();
            }
            System.out.println("All Connection closed");
        }
    }
}

Когда программа достигает линии LINE 39, я обновляю базу данных из бэкэнда для записи.Для TYPE_SCROLL_INSENSITIVE он не показывает обновленную запись, которую он должен делать, но для TYPE_SCROLL_SENSITIVE не выполняет желаемого поведения.Он должен показывать обновленную запись, но не показывать.Может кто-нибудь сказать, почему это так?

Я где-то читал, когда гуглил (не Java doc или JLS), что тонкий драйвер ODBC, драйвер OCI поддерживают объект INSENSITIVE ResultSet и не чувствительны.Это так?Если да, то почему и какой драйвер поддерживает оба?Если нет, то где я иду не так.

Я прошел по ссылке , но не указал на мой вопрос.Любое предложение будет оценено.

EDIT: добавлены эти строки для проверки поддержки

DatabaseMetaData meta = con.getMetaData();
System.out.println("{TYPE_SCROLL_INSENSITIVE, CONCUR_UPDATABLE} -> "+
                meta.supportsResultSetConcurrency(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE));
System.out.println("{TYPE_SCROLL_SENSITIVE, CONCUR_UPDATABLE} -> "+
                    meta.supportsResultSetConcurrency(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE));
System.out.println("{TYPE_SCROLL_SENSITIVE, CONCUR_READ_ONLY} -> "+
                    meta.supportsResultSetConcurrency(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY));

Ниже приведен результат, который я получил:

{TYPE_SCROLL_INSENSITIVE, CONCUR_UPDATABLE} -> true

{TYPE_SCROLL_SENSITIVE, CONCUR_UPDATABLE} -> true

{TYPE_SCROLL_SENSITIVE, CONCUR_READ_ONLY} -> true

1 Ответ

0 голосов
/ 10 февраля 2019

Как и в случае с другими функциями, которые не работают , вы должны прочитать документацию перед их использованием.

Важным является понятие окна

В реализации Oracle наборов результатов, чувствительных к прокрутке, используется концепция окна с размером окна, основанным на размере выборки.Размер окна влияет на частоту обновления строк в наборе результатов.

Таким образом, чтобы наблюдать за изменением каждой отдельной строки, вы должны установить размер выборки равным 1.

Обратите внимание, что не достаточно установить размер выборки для resultSet , поскольку размер выборки по умолчанию равен 10, а изменение действительно только для 11-й и последующих строк.

Поэтому размер выборки должен быть установлен на prepareStatement:

 def stmt = con.prepareStatement("""select id, val from test
 where  id between ? and ?  order by id""", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)
 stmt.setFetchSize(1)
 // set bind variables and execute statement

Теперь при каждом вызове rs.next() открывается новое окно, которое приводит к внутреннему вызову refreshRow

, которая получает текущие значения из базы данных.

Обратите внимание, что это поведение выполняется только для TYPE_SCROLL_SENSITIVE, для TYPE_SCROLL_INSENSITIVE не вызывается refreshRow, поэтому вы видите постоянные данные на начальном запросе даже при переключении окна.Вы можете вызвать refreshRow явно, чтобы увидеть тот же эффект.

Технически функциональность реализована с использованием двух курсоров.Первый соответствует используемому запросу, добавляя только столбец ROWID.

 select rowid as "__Oracle_JDBC_internal_ROWID__", id, val from test
 where  id between :1  and :2   order by id

Второй курсор вызывается при каждом переключении окна (т. Е. При размере выборки = 1 для каждой выбранной строки) простые внешние соединения присоединяются к сохраненномуrowid с запросом от первого курсора для повторного получения текущих данных.

WITH "__JDBC_ROWIDS__" AS (SELECT COLUMN_VALUE ID, ROWNUM NUM FROM TABLE(:1 ))
SELECT "__JDBC_ORIGINAL__".*
FROM (select rowid as "__Oracle_JDBC_internal_ROWID__", id, val from test
where  id between :2  and :3   order by id) "__JDBC_ORIGINAL__", "__JDBC_ROWIDS__"
WHERE "__JDBC_ORIGINAL__"."__Oracle_JDBC_internal_ROWID__"(+) = "__JDBC_ROWIDS__".ID
ORDER BY "__JDBC_ROWIDS__".NUM 

Есть похожие вопросы, но ни один из них не объясняет проблему, поэтому я не отмечаю этот вопрос как дублированный:

Поведение ResultSet.TYPE_SCROLL_SENSITIVE

JDBC ResultSet Type_Scroll_Sensitive

Тип набора результатов JDBC чувствителен к прокрутке

Краткий ответ является то, что размер выборки по умолчанию, который вы использовали, слишком велик, чтобы наблюдать обновление одной строки .

Тест был выполнен на Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 DriverVersion 12.2.0.1.0

...