2012-08-03 2 views
3

저는 그래프 데이터베이스로 시작해서 neo4j로 배우는 것이 가장 좋은 것으로 생각했습니다. 응용 프로그램 내에서 실행되는 neo4j의 임베디드 인스턴스가 있습니다 (JSF 기반). 애플리케이션의 사용 사례는 주로 그래프 DB 사용의 개념과 개선 사항을 배우고 또한 최선의 방법 (즉, 임베디드 또는 독립 실행 형)을 결정하는 데 도움이됩니다. 하지만 테스트 애플리케이션은 관계를 정의하는 기능 (예 : KNOWS, WORKS_WITH, WORKS_FOR 등)을 갖춘 매우 기본적인 연락처 앱으로, 이러한 관계를 기반으로 추천을 (즉, "알고 있을지도 모르는") 만들 수 있습니다.임베디드 neo4j 내에서 트랜잭션을 처리하는 가장 좋은 방법은 무엇입니까?

지금까지 기본 c.r.u.d 작업을 받았고 관계를 추가/제거 할 수 있습니다. 내 다음 단계는 실제로 그래프를 가로 지르는 것입니다 (제 생각에). 하지만 현재 실행중인 문제는 일단 서버와의 세션이 만료되면 저장소가 현재 사용 중이라고 불평하는 IllegalStateException 오류가 발생하지 않고 새 세션을 다시 설정할 수 없습니다. I 은 neo4j 인스턴스에서 절대로 shutdown을 호출하지 않기 때문이라고 생각합니다. 그래서 이것은 제가 거래를 처리하는 방식이 잘못되었다고 생각하게합니다. 그래서 누군가 제가 어떻게해야하는지에 대한 이해를 교정 할 수 있기를 바랍니다. 모든 도우미 방법은 꽤 많이는 getNode과 똑같은 방식으로 구성되어

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(); 
     } 
    }); 
} 
} 

(긴 ID : 여기

는 웹 클라이언트와 neo4j 사이의 작업을 처리하는 데 사용되는 내 헬퍼 클래스에서 몇 가지 방법이 있습니다) 및 createNode(), 물론 일부는 조금 더 많은 로직을 가지고 있지만 이것으로 배우기를 원하는만큼 매우 복잡한 것은 아닙니다.

마지막으로 내 질문에 :
*이 트랜잭션을 처리하는 올바른 방법입니까? 또는 어떤 유형의 트랜잭션 관리자를 구현해야합니까?
* 또한 매 트랜잭션마다 종료를 호출해야합니까?
* 응용 프로그램 수준이 아닌 클라이언트 세션 수준에서 처리해야합니까?

이 클래스는 서버 (http/jvm)가 재시작 될 때까지 (jsf, applicationScope에 익숙한 경우) 서버 메모리에 남아 있기 때문에 모든 트랜잭션 후에 shutdown을 호출하는 것이 약간 과잉으로 보입니다.

편집 : 나는 실제로 아래에서 어느 정도까지 다른 질문에 대답하기 때문에 받아 들여지는 것으로 표시하려고 찢어졌습니다. 따라서 왜 대답이 받아 들여지지 않았는지 궁금하다면 그 이유가 있습니다.

답변

1

거래 처리가 잘된 것 같습니다. 그리고 모든 거래가 끝난 후에는 종료하지 않아야합니다. 위에서 언급 한 것에서 singleton을 통해 neo4j db에 대한 핸들을 얻으십시오.이 클래스가 다시 인스턴스화 된 것처럼 보입니다. 문제가 있습니다. neo4j에 대한 다른 연결을 열려고하는데 허용되지 않습니다.

+0

구현 방법에 대한 내 생각을 확인해 주셔서 감사합니다. "이 클래스가 다시 인스턴스화 된 것처럼 보입니다. 문제가 있습니다." 예, 결론이 나옵니다. JSF가 applicationScope를 처리하는 방법은 응용 프로그램에 아무런 작업도 없다면 applicationScope를 디스크로 직렬화하고 누군가가 요청을하면 역 직렬화되고 결과가 다시 인스턴스화된다는 것입니다. 이 문제를 해결하기위한 방법이나이 동작을 가로채는 방법을 찾고 있습니다. 이 작업이 너무 크면 neo4j 서버 인스턴스가 설치됩니다. – keithstric

5

GraphDatabaseService를 SQLConnection 또는 이와 유사한 것으로 보지 마십시오. 긴 수명의 인스턴스이며 자주 중지되는 인스턴스는 오래 지속되는 그러한 인스턴스에서 얻은 많은 이점을 제거하고 많은 불필요한 오버 헤드를 부과합니다.

이렇게 tx.failure()를 호출 할 필요가 없습니다. A :

 
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

+2

Neo4j 2에서'finish'는 try-with-resources Java 7 '문을 사용할 수있게 해주는'close'를 위해 더 이상 사용되지 않습니다. – Tvaroh

+0

노드 무리를 만들면 어떻게됩니까? 여전히 커밋하지 않더라도 검색 가능합니까? – WantIt

3

자바 7 자동 종료 및 Neo4J 2.0 트랜잭션을 처리하는 방법 때문에이다

try (Transaction tx = graphDb.beginTx()) 
{ 
    ... 

    tx.success(); 
} 

은 그래서 명시 적 finish는 더 이상 필요하지 않습니다.

관련 문제