2016-10-04 5 views
1

バージョンを使用:春・データのNeo4j 4.2.0-BUILD-SNAPSHOT /のNeo4j-OGM 2.0.6-SNAPSHOT私が正しく関係をフェッチするの問題を抱えているのNeo4j OGMとの取引との関係エンティティマッピングの問題を

をエンティティ。 (:C -

  1. session.query(「MATCH(::: - [HAS_B B] A)

    次のフェッチ呼び出しは、(同じトランザクション内で実行される)一貫した結果を返しません)RETURNカウント(B)数として ")リターン1

  2. session.query(" MATCH(A) - [B:HAS_B] - (:C)の戻りB」)を正しくような関係エンティティを返しますRelationshipModelオブジェクト
  3. session.query(B.class、 "MATCH(:A) - [b:HAS_B] - (:C)戻り値b ")が返されます。

重要な注釈:すべての操作(作成、フェッチ)が同じトランザクションで行われた場合、正常であるようです。

私は関係エンティティを照会し、私のPOJOに自分でそれをマッピングするためにsession.query(文字列、地図)を使用して回避策を実装することができました。

@NodeEntity 
public class A { 
    public A() {} 
    public A (String name) { 
     this.name = name; 
    } 

    @GraphId 
    private Long graphId; 

    private String name; 

    @Relationship(type="HAS_B", direction=Relationship.OUTGOING) 
    private B b; 
} 

@RelationshipEntity(type="HAS_B") 
public class B { 
    public B() {} 
    public B (String name, A a, C c) { 
     this.name = name; 
     this.a = a; 
     this.c = c; 
    } 

    @GraphId 
    private Long graphId; 

    @StartNode 
    private A a; 

    @EndNode 
    private C c; 

    private String name; 
} 

@NodeEntity 
public class C { 
    public C() {} 
    public C (String name) { 
     this.name = name; 
    } 

    @GraphId 
    private Long graphId; 

    private String name; 
} 

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(loader=AnnotationConfigContextLoader.class, classes={MyTest.TestConfiguration.class}) 
public class MyTest { 
    @Autowired 
    private MyBean myBean; 

    @Configuration 
    @EnableAutoConfiguration 
    @EnableTransactionManagement 
    @EnableNeo4jRepositories("com.nagra.ml.sp.cpm.core.repositories") 
    public static class TestConfiguration { 
     @Bean 
     public org.neo4j.ogm.config.Configuration configuration() { 
      org.neo4j.ogm.config.Configuration config = new org.neo4j.ogm.config.Configuration(); 
      config.driverConfiguration().setDriverClassName("org.neo4j.ogm.drivers.embedded.driver.EmbeddedDriver"); 
      return config; 
     } 
     @Bean 
     public SessionFactory sessionFactory() { 
      return new SessionFactory(configuration(), "com.nagra.ml.sp.cpm.model"); 
     } 
     @Bean 
     public Neo4jTransactionManager transactionManager() { 
      return new Neo4jTransactionManager(sessionFactory()); 
     } 
     @Bean 
     public MyBean myBean() { 
      return new MyBean(); 
     } 
    } 

    @Test 
    public void alwaysFails() { 
     myBean.delete(); 
     myBean.create("1"); 
     try { Thread.sleep(2000); } catch (InterruptedException e) {} //useless 
     myBean.check("1"); // FAILS HERE ! 
    } 

    @Test 
    public void ok() { 
     myBean.delete(); 
     myBean.createAndCheck("2"); 
    } 
} 

@Transactional(propagation = Propagation.REQUIRED) 
public class MyBean { 

    @Autowired 
    private Session neo4jSession; 

    public void delete() { 
     neo4jSession.query("MATCH (n) DETACH DELETE n", new HashMap<>()); 
    } 

    public void create(String suffix) { 
     C c = new C("c"+suffix); 
     neo4jSession.save(c); 
     A a = new A("a"+suffix); 
     neo4jSession.save(a); 
     B bRel = new B("b"+suffix, a, c); 
     neo4jSession.save(bRel); 
    } 

    public void check(String suffix) { 
     //neo4jSession.clear(); //Not working even with this 
     Number countBRels = (Number) neo4jSession.query("MATCH (:A)-[b:HAS_B]-(:C) WHERE b.name = 'b"+suffix+"' RETURN count(b) as count", new HashMap<>()).iterator().next().get("count"); 
     assertEquals(1, countBRels.intValue()); // OK 
     Iterable<B> bRels = neo4jSession.query(B.class, "MATCH (:A)-[b:HAS_B]-(:C) WHERE b.name = 'b"+suffix+"' RETURN b", new HashMap<>()); 
     boolean relationshipFound = bRels.iterator().hasNext(); 
     assertTrue(relationshipFound); // FAILS HERE ! 
    } 

    public void createAndCheck(String suffix) { 
     create(suffix); 
     check(suffix); 
    } 
} 
+0

確認:他のトランザクションはコミット済みですか? –

+0

はい、Neo4jTransactionManagerのログによれば、最初の2つのトランザクションは正しく(delete()とcreate()呼び出しのためにコミットされます)。 3番目のトランザクション(check())は、アサーション例外のためにロールバックされます。また、ログには、各トランザクションごとに新しいセッションが作成されていることがわかります(「Neo4j OGMトランザクションのための新しいセッションのオープン[[email protected]]」) – tigrou83

+0

どのメソッドを使用しますか? MyBeanのメソッドを@Transactionalでマークしようとしましたが、問題は解決しません。 – tigrou83

答えて

4

このクエリsession.query(B.class, "MATCH (:A)-[b:HAS_B]-(:C) RETURN b")は、開始ノードまたは終了ノードではなくリレーションのみを返します。したがって、OGMはこれを水和できません。あなたはいつもあなたが同じトランザクション内でデータを作成し、フェッチの両方のときに動作するように見える理由は、セッションがすでにacのキャッシュされたコピーを持っていることである

のような関係と一緒に開始と終了ノードを返す必要がありますしたがってbは、キャッシュされた開始ノードと終了ノードで水和することができます。

0

まず、OGM 2.0.6-SNAPSHOTから2.1.0-SNAPSHOTにアップグレードしてください。私は問題の一部であるかもしれない前者の行動を見ている。

今すぐテストしてください。調査する価値のあることがここにいくつかあります。 @DirtiesContext

  • 用途:あなたはコンテキストに触れているように見えませんし、あなたが新しいセッション/トランザクションを取得しますので、テスト間のコンテキストをリセットするためにそれを使用しているならば、それはそれについて間違った道を進んでいます。代わりに@Transactionalを使用してください。 Spring JUnitランナーはこれを特別な方法で扱います(次の点を参照)。
  • トランザクションテストが自動的にロールバックされることに注意してください。ジャスパーは正しいです。春の統合テストはalways roll back by defaultになります。 JUnitテストがthen you will have to @Commit itをコミットしていることを確認したい場合。テストのセットアップ方法の良い例はhereです。
  • Spring Transactionプロキシの仕組みを理解しています。この混乱のなかで、同じクラスのトランザクションメソッドにトランザクションメソッドを単に呼び出すのではなく、SpringのTransactionalビヘイビアを適用することを期待してください。理由を簡単に書いてみると、hereが表示されます。

これらの問題に対処する場合は、すべて問題ありません。

+0

ご意見ありがとうございます! 2.1.0-SNAPSHOTを試しましたが、問題はまだあります。 @DirtiesContextを削除しようとしましたが、まだ問題があります。トランザクションの場合、Transactionalアノテーションは私のテストではなく私のSpring Beanで設定されているので、トランザクションは正しくコミットされます。そして、MyBeanメソッドへの外部呼び出しだけが新しいトランザクションを作成していることが分かります。したがって、すべてがトランザクションの周りで完全に動作しているようです。私はそれがキャッシュやマッピングに関連する問題だと思っています。 – tigrou83

+0

私の主張は、あなたのテストセットアップが正しくないということです。あなたの設定が間違っている場合は、試して試してみる方法は関係ありません。トランザクション分離とは、現在実行中のトランザクション以外のアサーションは表示されないことを意味します。テストの各呼び出しは、別々のセッション/トランザクションです。 Springはトランザクションをロールバックするので、次の呼び出しでは何も見えません。 – digx1

+0

申し訳ありませんが、なぜ私のテスト設定が間違っているのか分かりません。私自身を説明させてください。私の目標は、SDNアプリケーションでREST APIをテストすることです。 REST呼び出しが完了するたびに、新しいセッション/トランザクションが作成されます。私がSOに示した設定は、このセットアップの簡略化です。ここでは、 MyBeanがREST API実装の役割を担っています。私は私のテストがトランザクションであることを望んでいません。私のテストからMyBeanクラスへの各呼び出しは、新しいセッション/トランザクションを作成します。 – tigrou83

関連する問題