提前感谢您的关注和任何建议。我希望我对这个问题的解释足够清楚。
如主题一栏所述,我正在将基于java的项目升级到嵌入式API的第3版。不幸的是,我收到以下错误:
SEVERE:hasNext中的异常:语句已关闭。
代码如下,但这是解释。为了在我的应用程序代码和数据库代码(在本例中为Neo4j)之间提供一层隔离,我正在使用DAO模式。我正在分配ResourceIterator我从findNodes调用回到我正在定义的用户级迭代器中的变量。根据此页面(https://neo4j.com/docs/java-reference/current/javadocs/org/neo4j/graphdb/Transaction.html)
从执行的操作返回的所有ResourceIterables 交易内部将在交易时自动关闭 已提交或回滚。但请注意,ResourceIterator 如果你不打算用尽,应该尽快关闭 迭代器
这很清楚,似乎解释了为什么我得到例外。但必须有一些方法来返回迭代器供以后使用。至少我希望如此。想到的另一个选择是将所有节点存储在用户存储器中,以便我的用户级接口可以迭代它们,这将有点问题。我会注意到这段代码(曾经使用过GlobalGraphOperations类)在Neo4j 2中运行。但是这可能是Neo4j 2中的一个错误?请注意,我已尝试不关闭事务(甚至根本不使用事务)。
有什么想法吗?
这是问题的实际来源:它是我对用户可见结构表示节点的迭代器的定义。抛出异常的那一行是对hasNext的调用。
public boolean hasNext() {
// Wrap the neo4j iterator
boolean hasN = false;
GraphDatabaseService theDB = Neo4jDAOFactory.getTheNetworkDB();
Transaction tx = theDB.beginTx();
try {
hasN = nodeIterator.hasNext();
} catch (Exception e) {
// should send this back using the message logs eventually
this.logger.log (Level.SEVERE, "exception in hasNext: " + e.getMessage(), e);
} finally {
tx.close();
}
return hasN;
}
但如果没有看到它就没有意义:
public Iterator<NetworkNodeTransferObject>
getNetworkNodes(String nameSpace, String key, Object value){
Neo4jNetworkNodeDAOIterator theIterator = null;
GraphDatabaseService theDB = Neo4jDAOFactory.getTheNetworkDB();
Transaction tx = theDB.beginTx();
try {
Label newLabel = Label.label(nameSpace);
Iterator<Node> neo4jNodeList = theDB.findNodes(newLabel, key, value);
theIterator = new Neo4jNetworkNodeDAOIterator();
theIterator.nodeIterator = neo4jNodeList;
} catch (Exception e) {
// should send this back using the message logs eventually
this.logger.log (Level.SEVERE, "exception in getNetworkNodes: " + e.getMessage(), e);
} finally {
tx.close();
}
return theIterator;
}
由于 霍华德
答案 0 :(得分:0)
我将首先解决您的hasNext()
实施问题:此时您无法在某个新事务中包装nodeIterator.hasNext()
,它必须在事务的上下文中使用是它的创建。
所以基本上它不需要超过
public boolean hasNext() {
return nodeIterator.hasNext();
}
现在,关于您的事务问题:要返回迭代器,您需要保持事务至少与迭代器本身一样长。有多种方法可以做到这一点:
getNetworkNodes
或更高级别的来电中管理,因此getNetworkNodes
会预期交易存在而不关心其创建您可以将事务保存在用户级迭代器中,与nodeIterator
一起,但是可靠地关闭它可能会很棘手。 如果你总是使用迭代器直到结束,当你到达结束时或者当出现错误时(因为它可能会中断迭代),关闭事务应该可以解决问题:
public boolean hasNext() {
boolean hasN = nodeIterator.hasNext();
if (!hasN) {
tx.close();
}
return hasN;
}
public NetworkNodeTransferObject next() {
try {
Node node = nodeIterator.next();
// Create the NetworkNodeTransferObject
return networkNodeTo;
} catch (RuntimeException e) {
tx.close();
throw e;
}
}