如何在 JDBC 数据源级别限制从 Oracle 返回的行数?

Posted

技术标签:

【中文标题】如何在 JDBC 数据源级别限制从 Oracle 返回的行数?【英文标题】:How to limit number of rows returned from Oracle at the JDBC data source level? 【发布时间】:2008-11-26 10:59:07 【问题描述】:

有没有办法限制在 Tomcat 应用程序中在 Oracle 数据源级别返回的行?

似乎maxRows 仅在您在 Java 代码中的数据源上设置时才可用。将maxRows="2" 放在数据源上并不适用。

还有其他方法限制返回的行吗?无需更改代码?

【问题讨论】:

【参考方案1】:

这不是配置级别可用的东西。您可能需要仔细检查它是否按照您希望的方式执行:see the javadoc for setMaxRows。对于 Oracle,它仍然会为查询取回每一行,然后只删除范围之外的行。您确实需要使用 rownum 才能使其与 Oracle 一起正常工作,而您也不能在配置中这样做。

【讨论】:

【参考方案2】:

问题是为什么要限制返回的行数。这样做可能有很多原因。首先是限制数据库返回的数据。在我看来,这在大多数情况下是没有意义的,好像我只想获取某些数据然后我会使用不同的语句或添加过滤条件或其他东西。例如。如果您使用 Oracle 的 rownum,您并不确切知道哪些数据在您获得的行中,哪些数据不包括在内,因为您只是告诉数据库您想要行 x 到 y。 第二种方法是限制内存使用并提高性能,以便您从 JDBC 驱动程序获得的 ResultSet 不会包含所有数据。您可以使用Statement.setFetchSize() 限制ResultSet 保存的行数。如果将 ResultSet 中的游标移动到超出获取的行数,则 JDBC 驱动程序将从数据库中获取丢失的数据。 (在 Oracle 的情况下,数据库会将数据存储在 JDBC 驱动程序直接访问的引用游标中)。

【讨论】:

【参考方案3】:

*注意:以下代码仅作为示例提供。它没有 已测试 * 因此可能会伤害您自己或您的计算机,甚至会打您 在脸上。

如果您想避免修改您的 SQL 查询但仍希望拥有干净的代码(这意味着您的代码保持可维护性),您可以使用包装器设计解决方案。也就是说,通过使用封装现有类的一小组类,您可以无缝地为应用程序的其余部分实现您想要的,这些应用程序仍然认为它正在使用真实的 DataSource、Connection 和 Statement。

1 - 实现 StatementWrapper 或 PreparedStatementWrapper 类,具体取决于您的应用程序已经使用的内容。这些类是普通 Statement 或 PreparedStatement 实例的包装器。它们被简单地实现为使用内部语句作为完成所有工作的委托,除非这是一个 QUERY 语句(Statement.executeQuery() 方法)。只有在那种精确的情况下,包装器才会用以下两个字符串包围查询:“SELECT * FROM (” and ") WHERE ROWNUM

2 - 再写一个包装器:ConnectionWrapper,它包装一个 Connection,它在 createStatement() 中返回 StatementWrapper,在 prepareStatement() 中返回 PreparedStatementWrapper。这些是以前编码的类,将 ConnectionWrapper 的 delegateConnection.createStatement()/prepareStatement() 作为构造参数。

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 作为应用程序的 DataSource。如果您使用的是 JNDI (NamingContext),则此更改应该是微不足道的。

对所有这些进行编码既快速又非常简单,尤其是当您使用 Eclipse 或 IntelliJ 等智能 IDE 时,它们将自动实现委派方法。

【讨论】:

【参考方案4】:

如果你知道你将只处理一个表,那么在 where 语句中定义一个带有 rownum 的视图来限制行数。通过这种方式,行数在 DB 中得到控制,不需要在客户端应用程序的任何查询中指定。如果要更改返回的行数,请在执行查询之前重新定义视图。

更动态的方法是开发一个过程并传入许多行,并让该过程返回一个 ref_cursor 给您的客户端。这将具有避免对数据库进行硬解析并提高性能的优势。

【讨论】:

【参考方案5】:

好的,那就得改一下代码了。

该场景限制了临时报告工具,以便最终用户不会拉回太多记录并生成无法使用的报告。

我们已经在使用基于 Oracle 成本的资源管理。

【讨论】:

【参考方案6】:

看看这个page with a description 限制一次吸入 Java 应用程序的数量。正如另一篇文章指出的那样,数据库仍将提取所有数据,这更多是为了控制网络使用和 Java 端的内存。

【讨论】:

以上是关于如何在 JDBC 数据源级别限制从 Oracle 返回的行数?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 JDBC 从 Oracle 读取数据集?

Oracle 11g JDBC 预取键

JDBC Transaction 如何在 TRANSACTION_READ_COMMITTED 隔离级别锁定表?

如何使用JDBC连接oracle数据库

如何使用 jdbc 从 Oracle 中的结果集中获取模式名称?

Jdbc进阶