Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java syntax with MongoDB

Tags:

java

mongodb

I'm going through the intro to MongoDB for java. There's some example code to retrieve all the documents in a collection. The code works, but I find it a bit...clunky for lack of a better word. I'm wondering if there's a specific reason that makes it necessary. The given example is:

FindIterable<Document> iterable = db.getCollection("restaurants").find();
iterable.forEach(new Block<Document>() {
    @Override
    public void apply(final Document document) {
        System.out.println(document);
    }
});

Is there some reason a Block instance has to be created in every iteration of the forEach in the above example? Why not something a little more straightforward like:

FindIterable<Document> iterable = db.getCollection("restaurants").find();
for (Document document : iterable) {
    System.out.println(document);
}
like image 767
Hal50000 Avatar asked May 24 '15 14:05

Hal50000


People also ask

Can you use Java with MongoDB?

Connecting via Java. Assuming you've resolved your dependencies and you've set up your project, you're ready to connect to MongoDB from your Java application. Since MongoDB is a document database, you might not be surprised to learn that you don't connect to it via traditional SQL/relational DB methods like JDBC.

Can you use JDBC with MongoDB?

Using the MongoDB JDBC connectivity, it's easier to place a query with the database, introduce updates to the database, and call upon stored processes.


1 Answers

While you can certainly use the form that you suggested:

for (Document document : col.find()) {
    // do something
}

it introduces a problem when the body of the for loop throws an exception: if this happens the cursor will not be closed. The proper idiom to guard against that is to use MongoCursor (which implements Closeable) explicitly:

try (MongoCursor<Document> cursor = col.find().iterator()) {
    while (cursor.hasNext()) {
        System.out.println(cursor.next());
    }
}

The forEach method is just a bit of syntactic sugar to avoid the need for application code to worry about having to close the cursor manually like this.

If you don't want to create a new Block for each iteration, you can refactor your code pull out the anonymous inner class creation, e.g.:

Block<Document> block = new Block<Document>() {
    @Override
    public void apply(final Document document) {
        System.out.println(document);
    }
};
col.find().forEach(block);

Of course that's even clunkier, so if you are able to use Java 8, you can replace the whole thing with a lambda:

col.find().forEach((Block<Document>) document -> {
    System.out.println(document);
});

or in this case simply:

col.find().forEach((Block<Document>) System.out::println);

The lambda metafactory will ensure that no unnecessary objects are created.

like image 188
jyemin Avatar answered Oct 18 '22 02:10

jyemin