2017-03-09 9 views
0

私はSDN 4(v4.2.1)、Springブート(1.5.2)、Neo4j(v3.1.0)を使用していますが、save()メソッドで単純な関係を削除することはできません。Spring Data Neo4jとの関係を削除



    @NodeEntity 
    public class A extends MyModel { 

     @Relationship(type="link") 
     private B b; 

     //Getters and setters 
    } 

    @NodeEntity 
    public class B extends MyModel { 

     @Relationship(type="link", direction=Relationship.INCOMING) 
     private List as; 

     //Getters and setters 
    } 

    public interface ARepository implements GraphRepository { 

    } 

    public interface BRepository implements GraphRepository { 

    } 


     //Create relationship 
     A a a = ...; 
     B b = ...; 
     a.setB(b); 
     a = aRepository.save(a); // works 
     //Delete relationship 
     a.setB(null); 
     aRepository.save(a); // Not works 

AとBの関係を削除するにはどうすればよいですか?

編集

ありがとうございました。

フォームの検証後に行う方法。



     @PostMapping(FORM) 
     public String form(@Valid @ModelAttribute("object") A a, BindingResult result, Model model, RedirectAttributes att, HttpServletRequest request) { 
      log.info("/form"); 
      if (result.hasErrors()) { 
       return form(model, a, request); 
      } 
      try { 
       // a.getB() is null and a.getId() isn't null 
       a = aService.save(a); // a.getB() isn't delete 
       if (a.getId() == null) 
        att.addFlashAttribute(MSG, a.getName() + " : create !"); 
       else 
        att.addFlashAttribute(MSG, a.getName() + " : modify !"); 
      } catch (Exception e) { 
       model.addAttribute(MSG, e.getMessage()); 
       log.error(e.getMessage(), e); 
       return form(model, a, request); 
      } 
      return redirect(LISTE); 
     } 

ここでは、私のオブジェクトはセッションに含まれていませんが、idはspring mvcで埋められました。 bがドロップダウンリストで選択されました。

+0

@Transactionalで呼び出しの基本シーケンスをラップしましたか? – digx1

+0

はい、私は自分のメソッドで@Transactionalを使用します。 –

+0

これは間違いなく機能するはずです。ここでチケットをお持ちください:https://jira.spring.io/browse/DATAGRAPH zipやgithubのいずれかのコードサンプルがあれば、それを複製することができます。 – digx1

答えて

1

あなたは上記で定義されているコードは、プロジェクトと同じではありません。

@Transactional 
public void test() { 
    A a = new A(); 
    a.setName("a1"); 
    B b = new B(); 
    b.setName("b1"); 
    a.setB(b); 
    System.out.println(a); 
    System.out.println("id : "+a.getId()); 
    A a2 = aRepo.save(a); 
    System.out.println(a2); 
    Long id = a2.getId(); 
    System.out.println("id : "+id); 

    A a3 = new A(); 
    a3.setId(id); 
    a3.setName("a2"); 
    System.out.println(a3); 
    aRepo.save(a3); 
    System.out.println(aRepo.findOne(id)); // b must be null 
} 

起こって多くのものがここにありますので、試してみましょうと最初にそれを打破します。

  1. 新しいAは変数aで、それに関連するBで作成されます。
  2. aがデータベースに保存され、aのコピーがa2として返されます。この段階では、aa2の両方に、同じ内部グラフIDが設定されます(a.id == a2.id
  3. a3という新しいオブジェクトが作成されます。前のステップの内部グラフIDはa3(別名@GraphId)に設定され、Bの参照なしでデータベースに保存されます。
  4. ida2と同じデータベースからAが取得されます。

各ステップの表紙の下に何が起こっているのかを見てみましょう。

  1. まだOGM/SDNとの対話はありません。
  2. この時点でaとそのBの参照はデータベースに保存されています。 OGM/SDNのキャッシュはbへのリンクを持つaを保持し、データベースにはそれぞれのオブジェクトのidフィールドに保存されている内部Neo4j IDが割り当てられています。 aの参照コピーはa2に割り当てられます。
  3. この時点では、OGM/SDNとの対話はありません。この新しいオブジェクトは、save()が呼び出されるまで、OGMによって管理されません。この時点で、事は未定義になります。 OGMは、オブジェクトの内部IDを設定しようとすると、「添付」されていないので、これを破棄して代わりにSessionのキャッシュされた値を使用します。

@GraphIdの値を決して変更しないでください。実際には、実際にはそれが変更可能なプロパティではないので、設計上の賢明さに晒されるべきではありません。

問題を解決するには、新しいオブジェクトをインスタンス化して以前の呼び出しから状態を関連付けるのではなく、セッションから取得した値を使用します。

+0

githubでサンプルコードを変更しましたが、まだ動作しません。それはSDN 4.1.8で動作します。 –

+0

これはSpring Bootのバグです。私はSpring Bootチームの問題を提起しました。https://github.com/spring-projects/spring-boot/issues/8587 – digx1

+0

@RidgeIdylle SDN 4.1.8 spring-bootの有無にかかわらず(どのブートバージョン) –

関連する問題