Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jsp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java jstl&x27;什么是sql标记工作?_Java_Jsp_Web Applications_Jstl - Fatal编程技术网

Java jstl&x27;什么是sql标记工作?

Java jstl&x27;什么是sql标记工作?,java,jsp,web-applications,jstl,Java,Jsp,Web Applications,Jstl,我使用以下代码从jsp查询数据库,但我想了解更多关于幕后发生的事情 这是我的两个主要问题 标记是否直接访问结果集,或者查询结果是否存储在内存中的数据结构中 连接什么时候关闭 <%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %> <sql:query var="query" dataSource="${ds}" sql="${listQuery}"></sql:query> <

我使用以下代码从jsp查询数据库,但我想了解更多关于幕后发生的事情

这是我的两个主要问题

标记是否直接访问结果集,或者查询结果是否存储在内存中的数据结构中

连接什么时候关闭

<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>

<sql:query var="query" dataSource="${ds}" sql="${listQuery}"></sql:query>
<c:forEach var="row" items="${query.rows}" begin="0">
    ${row.data }
    ${row.more_data }
</c:forEach>

${row.data}
${row.more_data}

注意:我一直反对在jsp中运行查询,但我的结果集太大,无法存储在操作和jsp之间的内存中。使用此标记库看起来是最简单的解决方案。

这里的关键是:javax.servlet.jsp.jstl.sql.Result

这就是JSTL作为SQL查询结果使用的内容。如果您查看接口,它有以下方法:

public java.util.SortedMap[]getRows()

c:forEach“知道”javax.servlet.jsp.jstl.sql.Result,因为Result不是forEach所知道的任何东西(集合、数组、迭代器等)

因此,所有这些都意味着SQL查询将把整个结果集吸入RAM

如果因为不想将整个结果集加载到集合中而将查询移动到JSP中,那么SQL标记看起来不会为您解决这个问题

实际上,您应该查找值列表模式

但解决问题的“简单”方法是创建一个自定义迭代器,该迭代器“知道”您的结果集。这个函数包装一个结果集,并在遇到异常或结果运行时关闭所有内容(就像在forEach中一样)。某种特殊用途的东西


公共类ResultTiterator实现迭代器{

Connection con;
Statement s;
ResultSet rs;
Object curObject;
boolean closed;

public ResultSetIterator(Connection con, Statement s, ResultSet rs) {
    this.con = con;
    this.s = s;
    this.rs = rs;
    closed = false;
}

public boolean hasNext() {
    advance();
    return curObject != null;
}

public Object next() {
    advance();
    if (curObject == null) {
        throw new NoSuchElementException();
    } else {
        Object result = curObject;
        curObject = null;
        return result;
    }
}

public void remove() {
    throw new UnsupportedOperationException("Not supported yet.");
}

private void advance() {
    if (closed) {
        curObject = null;
        return;
    }
    if (curObject == null) {
        try {
            if (rs.next()) {
                curObject = bindObject(rs);
            }
        } catch (SQLException ex) {
            shutDown();
            throw new RuntimeException(ex);
        }
    }
    if (curObject == null) {
        // Still no object, must be at the end of the result set
        shutDown();
    }
}

protected Object bindObject(ResultSet rs) throws SQLException {
    // Bind result set row to an object, replace or override this method
    String name = rs.getString(1);
    return name;
}

public void shutDown() {
    closed = true;
    try {
        rs.close();
    } catch (SQLException ex) {
        // Ignored
    }
    try {
        s.close();
    } catch (SQLException ex) {
        // Ignored
    }
    try {
        con.close();
    } catch (SQLException ex) {
        // Ignored
    }
}
}


这自然是未经测试的。但由于JSTLs forEach可以与迭代器一起工作,因此它是可以真正传递给它的最简单的对象。这将阻止您将整个结果集加载到内存中。(有趣的是,值得注意的是,与迭代器的ResultSets行为几乎不同,但并非完全不同。)

基于org.apache.taglibs.standard.tag.common.sql.QueryTagSupport源代码的观察

taglib遍历ResultSet并将所有数据放入数组、映射和列表中。因此,在开始循环之前,所有内容都会加载到内存中

当遇到查询开始标记(doStartTag方法)时,将打开连接。当遇到查询结束标记(doEndTag方法)时,将检索结果。连接在doFinally方法中关闭


简而言之,这是非常糟糕的。

我在接近OP时遇到了同样的问题,那就是在JSTL的SQL标记库中关闭数据库连接时?。我也查看了QueryTagSupport的源代码,可以找到
doFinally()
方法。但我这里的问题是,从哪里调用它?@Gnanam-似乎doFinally()方法在“sql:query”标记的末尾执行。考虑到ResultSet在您有机会对其进行迭代之前已经加载到一个单独的数据结构中,这是有意义的。我相信通过
关闭“sql:query”标记
,您指的是
doEndTag()
方法。但我仍然没有发现从这里调用
doFinally()
方法。在
QueryTagSupport
类的整个源代码中,我找不到从任何地方调用的方法。有什么想法吗?doEndTag()方法是从已转换为Java类的JSP调用的。此调用存在于try/catch/finally块中。在finally块中,对标记对象调用doFinally。在我的例子中,类是org.apache.taglibs.standard.tag.rt.sql.QueryTag。QueryTag扩展了org.apache.taglibs.standard.tag.common.sql.QueryTagSupport,它实际上包含doFinally()方法并执行close()。