Как ограничить количество строк, возвращаемых из Oracle на уровне источника данных JDBC? - PullRequest
4 голосов
/ 26 ноября 2008

Существует ли способ ограничения строк, возвращаемых на уровне источника данных Oracle в приложении Tomcat?

Кажется, maxRows доступно только в том случае, если вы установите его в источнике данных в коде Java. Помещение maxRows="2" в источник данных не применяется.

Есть ли другой способ ограничить количество возвращаемых строк? Без изменения кода?

Ответы [ 6 ]

4 голосов
/ 26 ноября 2008

Это не то, что доступно на уровне конфигурации. Вы можете дважды проверить, что он делает то, что вы хотите, в любом случае: см. Javadoc для setMaxRows . В Oracle он все еще будет собирать все строки для запроса, а затем просто отбрасывать их за пределы диапазона. Вам действительно нужно использовать rownum, чтобы он хорошо работал с Oracle, и вы не можете сделать это ни в конфигурации.

1 голос
/ 24 февраля 2011

* Осторожно: приведенный ниже код приведен в качестве примера. Не имеет было проверено * Это может нанести вред себе или вашему компьютеру или даже ударить вас в лицо.

Если вы хотите избежать изменения ваших SQL-запросов, но при этом хотите иметь чистый код (что означает, что ваш код остается поддерживаемым), вы можете разработать решение с использованием оболочек. То есть, используя небольшой набор классов, обертывающих существующие, вы можете достичь того, чего хотите, без проблем для остальной части приложения, которое все еще будет думать, что оно работает с реальным DataSource, Connection и Statement.

1 - реализовать класс StatementWrapper или PreparedStatementWrapper, в зависимости от того, что ваше приложение уже использует. Эти классы являются обертками вокруг обычных экземпляров Statement или PreparedStatement. Они реализуются просто как использование внутреннего оператора в качестве делегата, который выполняет всю работу, кроме случаев, когда это оператор QUERY (метод Statement.executeQuery ()). Только в этой конкретной ситуации оболочка окружает запрос двумя следующими строками: «SELECT * FROM (» и «) WHERE ROWNUM <» + maxRowLimit. Ниже приведен базовый код обертки кода для DataSourceWrapper. </p>

2 - написать еще одну оболочку: ConnectionWrapper, которая оборачивает Connection, который возвращает StatementWrapper в createStatement () и PreparedStatementWrapper в prepareStatement (). Это ранее закодированные классы, которые принимают в качестве аргументов конструкции DelegateConnection.createStatement () / prepareStatement () объекта ConnectionWrapper в качестве аргументов конструкции.

3 - повторите шаг с DataSourceWrapper. Вот простой пример кода.

public class DataSourceWrapper implements DataSource
{
    private DataSource mDelegate;

    public DataSourceWrapper( DataSource delegate )
    {
        if( delegate == null ) { throw new NullPointerException( "Delegate cannot be null" );
        mDelegate = delegate;
    }

    public Connection getConnection(String username, String password)
    {
        return new ConnectionWrapper( mDelegate.getConnection( username, password ) );
    }

    public Connection getConnection()
    {
        ... <same as getConnection(String, String)> ...
    }
}

4 - Наконец, используйте этот DataSourceWrapper в качестве источника данных вашего приложения. Если вы используете JNDI (NamingContext), это изменение должно быть тривиальным.

Кодирование всего этого является быстрым и очень простым, особенно если вы используете интеллектуальную IDE, такую ​​как Eclipse или IntelliJ, которая будет автоматически реализовывать методы делегирования.

1 голос
/ 28 ноября 2008

Вопрос в том, почему вы хотите ограничить количество возвращаемых строк. Там может быть много причин, чтобы сделать это. Первый - ограничить данные, возвращаемые базой данных. По моему мнению, в большинстве случаев это не имеет смысла, так как если бы я хотел получить только определенные данные, я бы использовал другое утверждение или добавил бы условие фильтрации или что-то еще. Например. если вы используете rownum Oracle, вы точно не знаете, какие данные находятся в строках, которые вы получаете, а какие нет, поскольку вы просто указываете базе данных, что хотите, чтобы строка x была y.
Второй подход заключается в ограничении использования памяти и увеличении производительности, чтобы ResultSet, который вы получаете от драйвера JDBC, не включал все данные. Вы можете ограничить количество строк, удерживаемых ResultSet, используя Statement.setFetchSize () . Если вы переместите курсор в ResultSet за пределы числа выбранных строк, драйвер JDBC извлечет недостающие данные из базы данных. (В случае Oracle база данных будет хранить данные в ref-курсоре, к которому непосредственно обращается драйвер JDBC).

0 голосов
/ 20 февраля 2009

Взгляните на эту страницу с описанием ограничения количества всасывания в Java-приложение за один раз. Как отмечается в другом посте, БД будет по-прежнему извлекать все данные, это больше для контроля использования сети и памяти на стороне Java.

0 голосов
/ 02 декабря 2008

Хорошо, тогда изменение кода должно произойти.

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

Мы уже используем управление ресурсами на основе стоимости оракула. ​​

0 голосов
/ 26 ноября 2008

Если вы знаете, что будете иметь дело только с одной таблицей, определите представление с rownum в операторе where, чтобы ограничить количество строк. Таким образом, количество строк контролируется в БД и не требует указания как часть любого запроса клиентского приложения. Если вы хотите изменить количество возвращаемых строк, переопределите представление перед выполнением запроса.

Более динамичным методом было бы разработать процедуру и передать несколько строк, и заставить процедуру вернуть ref_cursor вашему клиенту. Это позволило бы избежать жесткого анализа базы данных и повысить производительность.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...