Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best method for retrieving data in XPages and Java

Tags:

xpages

I am sorry this isn't a 'coding' question, but after some considerable time on the learning path with XPages and Java I still struggle with finding definitive information on the correct way to carry out the basics.

When developing an XPages application using Java which is the best or most efficient method for accessing data?

1) Setting up and maintaining a View, with a column for every field in the document and retrieving data by ViewEntry.getColumnValues().get(int); i.e. not accessing the document and retrieving the data from the view. Which is what I have been doing but my View Columns are continuing to increase along with the hassle of maintaining column sequences. My understanding is this a faster method.

or

2) Just drop everything into a document using a View only when necessary, but in the main using Database.getDocumentByUNID().getItemValueAsString("field") and not worrying about adding lots of columns, far easier to maintain, but is accessing the document slowing things down?

like image 394
Mark Maden Avatar asked Oct 24 '25 14:10

Mark Maden


2 Answers

Neither 1) or 2).

Go this way to manage document's data in a Java class:

  • Read document's items all at once in your Java class into class fields
  • remember UNID in a class field too
  • recycle document after reading items
  • get document again with the help of UNID for every read/write and recycle afterwards

Database.getDocumentByUNID() is quite fast but call it only once for a document and not for every item.

Update

As you mentioned in a comment, you have a database with 50.000 documents of various types.

I'd try to read only those documents you really need. If you want to read e.g. all support ticket documents of a customer you would use a view containing support tickets sorted by customer (without additional columns). You would get the documents with getAllDocumentsByKey(customer, true) and put the Java objects (each based on a document) into a Map.

You can maintain a cache in addition. Create a Map of models (model = Java object for a document type) and use UNID as key. This way you can avoid to read/store documents twice.

like image 53
Knut Herrmann Avatar answered Oct 28 '25 04:10

Knut Herrmann


This is a really great question. I would first say that I agree 100% with Knut and that's how I code my objects that represent documents.

Below I've pasted a code example of what I typically do. Note this code is using the OpenNTF Domino API which among other things takes care of recycling for me. So you won't see any recycle calls.

But as Knut says - grab the document. Get what you need for it then it can be discarded again. When you want to save something just get the document again. At this stage you could even check lastModified or something to see of another save took place since the time you loaded it.

Sometimes for convenience I overload the load() method and add a NotesViewEntry : public boolean load(ViewEntry entry) {}

Then in there I could just get the document, in if it's a specific situation use view columns.

Now this works great when dealing with a single document at a time. It works really well if I want to loop through many documents for a collection. But if you get too many you might see some of the overheard start to slow things down. One app I have if I "injest" 30,000 docs like this into a collection it can get a little slow.

I don't have a great answer for this yet. I've tried the big view with many columns thing like it sounds like you did. I've tried creating a lower level basic version of the object with just needed fields and that was more designed to work on viewEntry and their columns. I don't have a great answer for that yet. Making sure you lazy load what you can is pretty important I think.

Anyway here's a code example that shows how I build most of my document driven objects.

package com.notesIn9.video;

import java.io.Serializable;
import java.util.Date;

import org.openntf.domino.Database;
import org.openntf.domino.Document;
import org.openntf.domino.Session;
import org.openntf.domino.View;
import org.openntf.domino.utils.Factory;

public class Episode implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private String title;
    private Double number;
    private String authorId;
    private String contributorId;
    private String summary;
    private String subTitle;
    private String youTube;
    private String libsyn;
    private Date publishedDate;
    private Double minutes;
    private Double seconds;

    private String blogLink;

    private boolean valid;
    private String unid;
    private String unique;
    private String creator;

    public Episode() {
        this.unid = "";

    }

    public void create() {

        Session session = Factory.getSession(); // this will be slightly
                                                // different if not using the
                                                // OpenNTF Domino API
        this.setUnique(session.getUnique());
        this.setCreator(session.getEffectiveUserName());
        this.valid = true;

    }

    public Episode load(Document doc) {

        this.loadValues(doc);
        return this;

    }

    public boolean load(String key) {

        // this key is the unique key of the document. UNID would be
        // faster/easier.. I just kinda hate using them and seeing them in URLS
        Session session = Factory.getSession();
        Database currentDb = session.getCurrentDatabase();
        Database db = session.getDatabase(currentDb.getServer(), "episodes.nsf");
        View view = db.getView("lkup_episodes");
        Document doc = view.getDocumentByKey(key); // This is deprecated because
                                                    // the API prefers to use
                                                    // getFirstDocumentByKey

        if (null == doc) {
            // document not found. DANGER
            this.valid = false;
        } else {

            this.loadValues(doc);

        }

        return this.valid;

    }

    private void loadValues(Document doc) {

        this.title = doc.getItemValueString("title");
        this.number = doc.getItemValueDouble("number");
        this.authorId = doc.getItemValueString("authorId");
        this.contributorId = doc.getItemValueString("contributorId");
        this.summary = doc.getItemValueString("summary");
        this.subTitle = doc.getItemValueString("subtitle");
        this.youTube = doc.getItemValueString("youTube");
        this.libsyn = doc.getItemValueString("libsyn");
        this.publishedDate = doc.getItemValue("publishedDate", Date.class);
        this.minutes = doc.getItemValueDouble("minutes");
        this.seconds = doc.getItemValueDouble("seconds");
        this.blogLink = doc.getItemValueString("blogLink");

        this.unique = doc.getItemValueString("unique");
        this.creator = doc.getItemValueString("creator");

        this.unid = doc.getUniversalID();
        this.valid = true;

    }

    public boolean save() {

        Session session = Factory.getSession();
        Database currentDb = session.getCurrentDatabase();
        Database db = session.getDatabase(currentDb.getServer(), "episodes.nsf");
        Document doc = null;

        if (this.unid.isEmpty()) {
            doc = db.createDocument();
            doc.replaceItemValue("form", "episode");
            this.unid = doc.getUniversalID();
        } else {
            doc = db.getDocumentByUNID(this.unid);
        }

        this.saveValues(doc);
        return doc.save();

    }

    private void saveValues(Document doc) {

        doc.replaceItemValue("title", this.title);
        doc.replaceItemValue("number", this.number);
        doc.replaceItemValue("authorId", this.authorId);
        doc.replaceItemValue("contributorId", this.contributorId);
        doc.replaceItemValue("summary", this.summary);
        doc.replaceItemValue("subtitle", this.subTitle);
        doc.replaceItemValue("youTube", this.youTube);
        doc.replaceItemValue("libsyn", this.libsyn);
        doc.replaceItemValue("publishedData", this.publishedDate);
        doc.replaceItemValue("minutes", this.minutes);
        doc.replaceItemValue("seconds", this.seconds);
        doc.replaceItemValue("blogLink", this.blogLink);

        doc.replaceItemValue("unique", this.unique);
        doc.replaceItemValue("creator", this.creator);

    }

    // getters and setters removed to condense code.


    public boolean remove() {

        Session session = Factory.getSession();
        Database currentDb = session.getCurrentDatabase();
        Database db = session.getDatabase(currentDb.getServer(), "episodes.nsf");

        if (this.unid.isEmpty()) {
            // this is a new Doc
            return false;

        } else {

            Document doc = db.getDocumentByUNID(this.getUnid());
            return doc.remove(true);

        }

    }

}
like image 28
David Leedy Avatar answered Oct 28 '25 03:10

David Leedy



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!