繁体   English   中英

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

[英]How to limit number of rows returned from Oracle at the JDBC data source level?

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

似乎只有在Java代码中的数据源上设置maxRows才可用。 在数据源上放置maxRows="2"不适用。

有没有其他方法限制返回的行? 没有代码更改?

它不是配置级别可用的东西。 您可能需要仔细检查它是否按照您的意愿执行操作: 请参阅setMaxRows的javadoc 对于Oracle,它仍然会为查询提取每一行,然后只删除范围之外的那些。 您确实需要使用rownum使其与Oracle一起使用,并且您无法在配置中执行此操作。

问题是为什么要限制返回的行数。 这可能有很多原因。 第一种方法是仅限制数据库返回的数据。 在我看来,在大多数情况下这没有任何意义,好像我只想获得某些数据然后我会使用不同的语句或添加过滤条件等。 例如,如果您使用Oracle的rownum,您并不确切知道您获得的行中包含哪些数据以及未包含哪些数据,因为您只需告诉数据库您希望第x行为y。
第二种方法是限制内存使用并提高性能,以便从JDBC驱动程序获得的ResultSet不会包含所有数据。 您可以使用Statement.setFetchSize()限制ResultSet保留的行数。 如果将ResultSet中的光标移动到提取的行数之外,则JDBC驱动程序将从数据库中获取缺少的数据。 (在Oracle的情况下,数据库将数据存储在由JDBC驱动程序直接访问的引用游标中)。

* 注意:下面的代码是纯粹的例子。 它尚未经过测试*因此可能会伤害您自己或您的计算机,甚至可能会让您不知所措。

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

1 - 根据应用程序已经使用的内容,实现StatementWrapper或PreparedStatementWrapper类。 这些类是普通Statement或PreparedStatement实例的包装器。 它们只是使用内部语句作为委托执行所有工作,除非这是一个QUERY语句(Statement.executeQuery()方法)。 只有在这种精确的情况下,包装器才会通过以下两个字符串围绕查询:“SELECT * FROM(”和“)WHERE ROWNUM <”+ maxRowLimit。 有关基本代码包装器代码,请参阅下面的DataSourceWrapper查找方式。

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,它将自动实现委派方法。

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

一个更动态的方法是开发一个过程并传入许多行,并让过程将ref_cursor返回给您的客户端。 这样做的好处是可以避免对DB进行硬解析,并提高性能。

好的,代码改变它必须是。

该方案限制了特定报告工具,以便最终用户不会撤回太多记录并生成无法使用的报告。

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

请查看此页面,其中描述了限制一次吸入Java App的程度。 正如另一篇文章指出的那样,数据库仍然会提取所有数据,这更多的是用于控制网络使用和Java端的内存。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM