尝试使用MongoDB BulkWriteOperation时出现java.lang.IllegalStateException

时间:2014-09-12 18:39:53

标签: java mongodb exception queue

我有这个代码,一旦ArrayBlockingQueue填充它的配额,就会将文件转储到MongoDB中。当我运行代码时,它似乎只运行一次然后给我一个堆栈跟踪。我的猜测是BulkWriteOperation有人必须'重置'或重新开始。

另外,我在构造函数中创建了BulkWriteOperations ...

bulkEvent = eventsCollection.initializeOrderedBulkOperation();
bulkSession = sessionsCollection.initializeOrderedBulkOperation();

这是堆栈跟踪。

10 records inserted
java.lang.IllegalStateException: already executed
    at org.bson.util.Assertions.isTrue(Assertions.java:36)
    at com.mongodb.BulkWriteOperation.insert(BulkWriteOperation.java:62)
    at willkara.monkai.impl.managers.DataManagers.MongoDBManager.dumpQueue(MongoDBManager.java:104)
    at willkara.monkai.impl.managers.DataManagers.MongoDBManager.addToQueue(MongoDBManager.java:85)

以下是队列的代码:

public void addToQueue(Object item) {
        if (item instanceof SakaiEvent) {
            if (eventQueue.offer((SakaiEvent) item)) {
            } else {
                dumpQueue(eventQueue);
            }

        }
        if (item instanceof SakaiSession) {
            if (sessionQueue.offer((SakaiSession) item)) {
            } else {
                dumpQueue(sessionQueue);
            }
        }

    }

以下是从队列中读取的代码,并将它们添加到BulkWriteOperation(initializeOrderedBulkOperation)以执行它,然后将其转储到数据库中。只写了10个文件然后就失败了。

private void dumpQueue(BlockingQueue q) {
        Object item = q.peek();
        Iterator itty = q.iterator();
        BulkWriteResult result = null;

        if (item instanceof SakaiEvent) {
            while (itty.hasNext()) {
                bulkEvent.insert(((SakaiEvent) itty.next()).convertToDBObject());
                //It's failing at that line^^
            }
            result = bulkEvent.execute();

        }
        if (item instanceof SakaiSession) {
            while (itty.hasNext()) {
                bulkSession.insert(((SakaiSession) itty.next()).convertToDBObject());
            }
            result = bulkSession.execute();
        }

        System.out.println(result.getInsertedCount() + " records inserted");
    }

1 个答案:

答案 0 :(得分:4)

在这种情况下,general documentation适用于所有驱动程序实现:

  

"执行后,如果不重新初始化,则无法重新执行Bulk()对象。"

所以有效的.execute()方法"排水"已发送给它的当前操作列表,现在包含有关命令实际发送方式的状态信息。因此,您无法在不重新初始化的情况下在同一实例上添加更多条目或再次呼叫.execute()

因此,在每个" Bulk"上调用执行后对象,你需要再次调用intialize:

bulkEvent = eventsCollection.initializeOrderedBulkOperation();
bulkSession = sessionsCollection.initializeOrderedBulkOperation();

在您的函数中的每个.execute()调用之后,每个行都会分别再次放置。然后进一步调用这些实例可以添加操作并再次调用execute继续循环。

请注意"批量"操作对象将存储您想要放入的项目,但会将对服务器的请求分解为最多1000个项目。执行后,操作列表的状态将准确反映出如何进行检查。