Xpages:如何从 CacheBean 访问数据库

Xpages: How to access database from CacheBean

我有一个名为 PCConfig 的 cacheBean,我想在其中存储对数据库的引用,以便我可以在其他 Java 方法中访问它们。

这是我的 cacheBean 的相关部分:

package com.scoular.cache;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Vector;
import org.openntf.domino.utils.Factory;
import org.openntf.domino.xsp.XspOpenLogUtil;
import org.openntf.domino.Database;
import org.openntf.domino.Session;
import org.openntf.domino.View;
import org.openntf.domino.ViewEntry;
import org.openntf.domino.ViewNavigator;

public class PCConfig implements Serializable {

    private static final long serialVersionUID = 1L;

    private static Database PCDataDB;

    // @SuppressWarnings("unchecked")
    private void initConfigData() {
        try {
            loadStatus();
            loadGeoLocations();
            loadModels();
            loadDatabases();
        } catch (Exception e) {
            XspOpenLogUtil.logError(e);
        }
    }

    public PCConfig() {
        initConfigData();
    }

    //Getters   

    public static Database getPCDataDB() {
        return PCDataDB;
    }

    public static void setPCDataDB(Database dataDB) {
        PCDataDB = dataDB;
    }

    public static void loadDatabases() {
        loadPCDataDB();     
    }

    public static void loadPCDataDB() {
        Session session = Factory.getSession();
        PCConfig.PCDataDB = session.getDatabase(thisDB.getServer(),"scoApps\PC\PCData.nsf", false);
    }


    }
}

在另一个 java class 中,我导入了 PCConfig class 并尝试使用此方法 getPCDataDB()。我也试过PCConfig.PCDataDB。

我总是报错空指针异常。

我做错了什么?

public void loadByUnid(String unid) {
    try {
        Document doc = PCConfig.getPCDataDB().getDocumentByUNID(unid);
        if (null == doc) {
            System.out.println("Document not found");
        } else {
            loadValues(doc);
        }
    } catch (Exception e) {
        XspOpenLogUtil.logError(e);
    }
}

您调用静态方法getPCDataDB()。因为它是静态的,所以您不需要实例化 class。但是,此时您的私有字段 Database PCDataDB 尚未初始化。只有在实例化 class 时才会发生这种情况。这就是你得到空指针异常的原因。

我猜 PCConfig 是一个托管 bean。如果您在 SSJS 中调用非静态方法,它将自动实例化。因此,删除 class 中的所有 static,它应该可以工作。如果你想在 Java 中使用 class 然后在调用 getPCDataDB() 之前实例化 class:

    PCConfig pcConfig = new PCConfig();
    Document doc = pcConfig.getPCDataDB().getDocumentByUNID(unid);

不建议将 Domino 对象保留为 class 字段(如您的 Database PCDataDB),因为它们不可序列化。它们可能会随着时间的推移而被回收,特别是如果 class 对象驻留在像应用程序范围这样的长期范围内。最好将数据本身保存在字段中或您的案例数据库的服务器名称和路径中,以便您可以在需要时再次打开数据库。

顺便说一句 private Database PCDataDB 应该是 private Database pCDataDB。惯例是只有 class 个名称和接口以大写字母开头。

正如 Knut 所说,将数据库存储在静态 class 中是行不通的。通常您需要将服务器和数据库路径存储为单独的变量。但是由于您使用的是 OpenNTF Domino API,您可以利用 Database.getApiPath() ,其中 returns 和 "metaReplicaID" - 服务器名和副本 ID 的组合。您可以存储它,并且可以直接引用数据库所在的位置。然后,您可以在需要时使用 session.getDatabase(metaReplicaID) 检索数据库。