2013-06-20 11 views
5

これはthis questionに関連していますが、以下の例は短くなっています。Play + Ebean + JPA:OneToOneマッピングで削除をカスケードにする

私は、AとBの2つのエンティティを1対1の関係で持っています。 Aの場合、Bは任意であり、そしてここに私の最初の試みだ私は、カスケードにしたいA.を持っている必要があり、すべてのBはAからBに削除します。Ebeanは「オプション」無視するようにしかし

@Entity 
public class A extends Model { 

    @Id 
    private Long id; 

    @OneToOne(optional = true, mappedBy = "a", cascade = CascadeType.REMOVE, orphanRemoval = true) 
    private B b; 

} 

@Entity 
public class B extends Model { 

    @Id 
    private Long id; 

    @OneToOne(optional = false) 
    private A a; 

} 

、それはそうです注釈は、私はIDが1で保存されたAのための検索を実行すると、以下のSQLが実行されるため:つまり

select t0.id c0, t1.id c1 
from a t0 
join b t1 on t1.a_id = t0.id 
where t0.id = 1 

を、それが内側の代わりの左は、検索をすると失敗する原因となる、参加しません私は@JoinColumnなど様々な組み合わせを試したことがありません。私が見つけたやや満足できる回避策は、A-to-Bを「擬似」1対多の関係としてモデル化することです。より良い解決策はありますか?これはバグですか、それともEbeanの既知の/明記された制限ですか?

答えて

1

解決策を見つけました。私はこのマッピングの方向を変えました。そこでmappedBy = "a"Aクラスから削除し、mappedBy = "b"Bクラスに追加しました。

@Entity 
public class A extends Model { 

    @Id 
    private Long id; 

    @OneToOne(optional = true, cascade = CascadeType.REMOVE, orphanRemoval = true) 
    private B b; 

... 
} 


@Entity 
public class B extends Model { 

    @Id 
    private Long id; 

    @OneToOne(optional = false, mappedBy = "b") 
    private A a; 

    private String name; 

    ... 
} 

が、私はこのテストをより面白くするためにBクラスのnameフィールドを追加しました:
だからコードは今、このように見えます。

私のテストmedhod:

@Test 
public void abTest() { 
    FakeApplication app = Helpers.fakeApplication(Helpers.inMemoryDatabase()); 
    Helpers.start(app); 

    A a = new A(); 
    B b = new B(); 
    a.setId(1L); 
    b.setId(2L); 
    a.setB(b); 
    b.setA(a); 
    b.setName("bbb"); 

    Ebean.save(b); 
    Ebean.save(a); 

    A fa = Ebean.find(A.class, 1L); 
    System.out.println("a.id: "+fa.getId()); 
    System.out.println("a.b.id: "+fa.getB()); 
    System.out.println("a.b.name: "+fa.getB().getName()); 

    A a1 = new A(); 
    a1.setId(3L); 
    Ebean.save(a1); 
    A fa1 = Ebean.find(A.class, 3L); 
    System.out.println("a1.id: "+fa1.getId()); 
    System.out.println("a1.b.id: "+fa1.getB()); 

    B fb = Ebean.find(B.class, 2L); 
    System.out.println("b.id: "+fb.getId()); 
    System.out.println("b.name: "+fb.getName()); 
    System.out.println("b.a.id: "+fb.getA().getId()); 
} 

そして、このテストの結果は次のとおりです。A.bnullであるかどうか

[debug] c.j.b.PreparedStatementHandle - insert into b (id, name) values (2,'bbb') 
[debug] c.j.b.PreparedStatementHandle - insert into a (id, b_id) values (1,2) 
[debug] c.j.b.PreparedStatementHandle - select t0.id c0, t0.b_id c1 from a t0 where t0.id = 1 
a.id: 1 
a.b.id: [email protected] 
[debug] c.j.b.PreparedStatementHandle - select t0.id c0, t0.name c1, t1.id c2 from b t0 left outer join a t1 on t1.b_id = t0.id where t0.id = 2 
a.b.name: bbb 
[debug] c.j.b.PreparedStatementHandle - insert into a (id, b_id) values (3,'[SQL NULL of type -5]') 
[debug] c.j.b.PreparedStatementHandle - select t0.id c0, t0.b_id c1 from a t0 where t0.id = 3 
a1.id: 3 
a1.b.id: null 
[debug] c.j.b.PreparedStatementHandle - select t0.id c0, t0.name c1, t1.id c2 from b t0 left outer join a t1 on t1.b_id = t0.id where t0.id = 2 
b.id: 2 
b.name: bbb 
b.a.id: 1 

だから、このコードは良い関係なく動作します。ログに表示されるように、今度は joinの代わりに left outer joinがあります。