2012-08-03 107 views
3

我剛剛開始使用Graph數據庫,並認爲最好學習neo4j。我有一個在應用程序中運行的嵌入式neo4j實例(基於JSF)。應用程序的用例主要是讓我學習使用圖形數據庫的概念和陷阱,並幫助確定最佳方式(即嵌入式或獨立式)。但是我的測試應用程序是一個非常基本的聯繫人應用程序,能夠定義關係(即KNOWS,WORKS_WITH,WORKS_FOR等),並最終能夠根據這些關係提供建議(即「你也許也知道」)。處理嵌入式neo4j內交易的最佳方式?

到目前爲止,我已經有了基本的c.r.u.d操作,並且可以添加/刪除關係。我的下一步將是實際開始遍歷圖(我認爲)。但是我現在遇到的問題是一旦我與服務器的會話過期,我不能重新建立一個新的會話,而沒有得到IllegalStateException錯誤,抱怨商店當前正在使用。我認爲,這是因爲我從來沒有在neo4j實例上調用shutdown。所以這讓我認爲我處理交易的方式都是錯誤的,所以我希望有人能夠糾正我的理解(或根據具體情況可能會誤解)我應該如何解決這個問題。

下面是我的助手類的一些方法正被用來處理Web客戶端和Neo4j的之間的操作:

public class NeoNodeUtils { 
private GraphDatabaseService graphDb; 

public NeoNodeUtils() { 
    setup(); 
} 

public void setup() { 
    GraphDatabaseFactory neoFactory = new GraphDatabaseFactory(); 
    setGraphDb(neoFactory.newEmbeddedDatabase("Morpheus")); 
    registerShutdownHook(); 
} 

public GraphDatabaseService getGraphDb() { 
    return graphDb; 
} 

public void setGraphDb(GraphDatabaseService graphDb) { 
    this.graphDb = graphDb; 
} 

public Node getNode(Long id) { 
    Transaction tx = getGraphDb().beginTx(); 
    Node node = null; 
    try { 
     node = getGraphDb().getNodeById(id); 
     tx.success(); 
    } catch (Exception e) { 
     tx.failure(); 
     e.printStackTrace(); 
    } finally { 
     tx.finish(); 
     return node; 
    } 
} 

public Node createNode() { 
    Transaction tx = getGraphDb().beginTx(); 
    Node node = null; 
    try { 
     node = graphDb.createNode(); 
     System.out.println("new nodeId = " + node.getId()); 
     tx.success(); 
    } catch (Exception e) { 
     tx.failure(); 
     e.printStackTrace(); 
    } finally { 
     tx.finish(); 
     return node; 
    } 
} 

public Node addNodeProperty(Node node, String propertyName, Object propertyValue) { 
    Transaction tx = getGraphDb().beginTx(); 
    try { 
     node.setProperty(propertyName, propertyValue); 
     tx.success(); 
    } catch (Exception e) { 
     tx.failure(); 
     e.printStackTrace(); 
    } finally { 
     tx.finish(); 
     return node; 
    } 
} 

public void shutDown() { 
    graphDb.shutdown(); 
} 

public void registerShutdownHook() { 
    Runtime.getRuntime().addShutdownHook(new Thread() { 
     @Override 
     public void run() { 
      graphDb.shutdown(); 
     } 
    }); 
} 
} 

每一個輔助方法,是相當多的結構作爲getNode完全相同的方式(長ID )和createNode(),當然有些更多的邏輯,但沒有什麼非常複雜的,因爲我只是想學習這一點。

因此,最後對我的問題:
*這是處理這些交易的正確方法嗎?或者,我是否應該實施某種類型的交易管理器?
*另外,我應該在每次交易後調用關機嗎?
*也許這應該在客戶端會話級別而不是應用程序級別處理?

在服務器(http/jvm)重新啓動之前(如果您熟悉jsf,applicationScope),這個類將一直保留在服務器內存中,因此在每次事務之後調用shutdown會有點矯枉過正。

編輯:我實際上在下面哪個答案上撕下來標記爲接受,因爲它們都在某種程度上回答我的問題。所以,如果你想知道爲什麼答案不被接受,那就是爲什麼。

回答

1

您的交易處理似乎很好。不,你不應該在每次交易後關閉。 只需通過一個單例處理neo4j數據庫 - 從上面提到的內容來看,它看起來像這個類被重新實例化,這就是問題 - 它試圖打開另一個連接到neo4j,這是不允許的。

+0

感謝您驗證我對如何實現這一點的想法。 「它看起來像這個類被重新實例化,這就是問題」 是的,這是我開始接觸的結論。我認爲JSF處理applicationScope的方式是,如果應用程序沒有任何活動,那麼它將applicationScope序列化到磁盤,並且一旦有人發出請求,它將被反序列化並且結果被重新實例化。我正在尋找解決此問題的方法或攔截此行爲的方法。如果這個任務太大,那麼neo4j服務器的一個實例就會被安裝。 – keithstric 2012-08-06 15:55:38

5

不要將GraphDatabaseService看作是SQLConnection或類似的,它是一個長期存在的實例,並且經常停止它會從長期存在的這種實例中獲得很多好處,並且會產生大量不必要的額外開銷。

你不需要像這樣調用tx.failure()。一個簡單的:

 
public Node createNode() { 
    Transaction tx = getGraphDb().beginTx(); 
    try { 
     Node node = graphDb.createNode(); 
     System.out.println("new nodeId = " + node.getId()); 
     tx.success(); 
     return node; 
    } finally { 
     tx.finish(); 
    } 
}

罰款,因爲一個事務只被視爲成功,如果success()被調用,否則會回滾。另外讀取操作不需要在交易中完成,因此:

 
public Node getNode(Long id) { 
    return getGraphDb().getNodeById(id); 
} 

就足夠了。

+0

感謝您的澄清,您是否有任何SQLConnection的例子? – keithstric 2012-08-06 15:50:11

+2

請注意,在Neo4j 2中,'finish'不贊成使用'close',它允許使用try-with-resources Java 7'語句。 – Tvaroh 2013-12-03 18:58:37

+0

那麼如果我們創建一堆節點會發生什麼,即使我們還沒有提交它們,它們是否可以搜索? – WantIt 2016-05-29 02:59:25

3

由於Java 7自動關閉和Neo4j的2.0來處理事務的方式是:

因此,不再需要
try (Transaction tx = graphDb.beginTx()) 
{ 
    ... 

    tx.success(); 
} 

明確finish