ご注意とアドバイスを事前にお寄せいただきありがとうございます。問題の説明が十分に分かりやすいことを願っています。埋め込みJava APIを使用してNeo4j 2から3にアップグレードする際の問題:hasNextIOの例外
私は、Javaベースのプロジェクトを組み込みAPIのバージョン3にアップグレードしています。残念ながら、次のエラーが表示されます。
重大度:hasNextの例外:文が閉じられました。
コードは次のとおりですが、ここで説明します。私のアプリケーションコードとデータベースコード(この場合はNeo4j)の間に分離レイヤーを提供するために、私はDAOパターンを使用しています。私は定義しているユーザーレベルのイテレータの変数にfindNodesコールから戻ってきているResourceIteratorを割り当てています。十分に明確だと私は例外を取得しています理由を説明するようで、このページ(https://neo4j.com/docs/java-reference/current/javadocs/org/neo4j/graphdb/Transaction.html)
All ResourceIterables that where returned from operations executed inside a transaction will be automatically closed when the transaction is committed or rolled back. Note however, that the ResourceIterator should be closed as soon as possible if you don't intend to exhaust the iterator
によります。しかし、後で使用するためにイテレータを返す方法がいくつかあります。少なくとも私はそう願っています。もう1つの選択肢は、すべてのノードをユーザーのメモリに格納して、ユーザーレベルのインターフェイスを反復処理できるようにすることです。これは少し問題になります。私は、このコード(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;
}
おかげ ハワード
を情報に感謝します。 1つのさらなる質問:トランザクションをイテレータに格納し、イテレータが最後まで消費されなかったとします。イテレータが範囲外になると、トランザクションは終了しますか?それに頼ることは合理的ですか? – HowardLander
いいえ、それは絶対に閉じられません: 'Transaction'実装が' finalize() 'メソッドを実装してガベージコレクション中にトランザクションを閉じる機会を得る必要があり、それは本当に脆いです(GCオーバーヘッドを追加します)。イテレータ全体を消費したくない場合は、トランザクションを手動で閉じることができる必要があります。 Neo4jの 'ResourceIterable'のように、サブインターフェース' ResourceIterator extends Iterator、AutoCloseable'を作成し、それを明示的にまたはtry-with-resourcesブロックを介して閉じます。 –