سؤال

أنا باستخدام التعليمات البرمجية التالية إلى الاستعلام عن قاعدة بيانات من jsp, ولكن أود أن أعرف المزيد حول ما يحدث وراء الكواليس.

هذه هي بلدي اثنين من المسائل الأساسية.

لا الوسم الوصول ResultSet مباشرة, أو هو نتيجة الاستعلام يجري تخزينها في datastructure في الذاكرة ؟

عندما يتم الاتصال مغلقة ؟

<%@ 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>

ملاحظة:لقد كنت دائما ضد تشغيل الاستعلامات في jsp, ولكن نتيجة مجموعة كبيرة جدا إلى مخزن في الذاكرة بين العمل و jsp.باستخدام هذا الوسم مكتبة يبدو أسهل حل.

هل كانت مفيدة؟

المحلول

الملاحظات استنادا إلى مصدر org.أباتشي.taglibs.القياسية.الوسم.المشتركة.sql.QueryTagSupport

على taglib يخترق من خلال ResultSet و يضع كافة البيانات في مصفوفات والخرائط والقوائم.لذلك ، كل شيء يتم تحميلها في الذاكرة حتى قبل أن تبدأ حلقات.

فتح الاتصال عند الاستعلام بداية الوسم واجه (doStartTag الأسلوب).النتائج استرجاعها عند الاستعلام نهاية الوسم واجه (doEndTag الأسلوب).يتم إغلاق الاتصال في doFinally الأسلوب.

هذا باختصار هو مروعا تماما.

نصائح أخرى

الشيء الرئيسي هنا هو هذا:javax.بريمج.jsp.jstl.sql.نتيجة

هذا ما JSTL يستخدم نتيجة استعلام SQL.إذا نظرتم إلى الواجهة ، فقد هذه الطريقة:

العامة جافا.util.SortedMap[] getRows()

ج:forEach "يعلم" عن javax.بريمج.jsp.jstl.sql.النتيجة لأن النتيجة ليست أي شيء آخر forEach يعرف عن (مجموعات ، المصفوفات ، التكرار ، إلخ).

لذلك ، كل ذلك يعني أن استعلام SQL سوف تمتص كامل مجموعة النتائج في ذاكرة الوصول العشوائي.

إذا كنت انتقل الاستعلام الخاص بك في JSP لأنك لم ترغب في تحميل كامل نتيجة مجموعة إلى مجموعة ، ثم إنها لا تبدو مثل SQL الوسم سيتم حل هذه المشكلة بالنسبة لك.

في الحقيقة يجب أن ننظر تصل قيمة القائمة نمط.

ولكن "بسيطة" حل المشكلة سوف يتم إنشاء مخصص مكرر على أن "يعلم" عن ResultSet.هذا واحد يلتف مجموعة نتائج ويغلق كل شيء إذا واجه استثناء أو إذا كانت نتيجة يعمل به بالطبع (كما كان في forEach).نوع خاص الغرض الشيء.

public class ResultSetIterator implements Iterator {

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 السلوك.)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top