2

spring-data-neo4j 4 データ モデルで継承が使用されている場合、エンド ノード タイプに基づいてリレーションシップを読み込んで判別するときに、スーパー クラスが判別子として使用されていることに気付きました。spring-data-neo4j-4 にサブクラスをディスクリミネータとして強制的に使用させる方法はありますか?

たとえば、左側に次のようなデータ モデル (クラス ダイアグラム) があり、右側にその neo4j データベース表現があるとします。

クラス図とneo4j表現

現在、次の行に沿ったコードを持つ Owner エンティティがあるとします。

@NodeEntity
class Owner extends BaseNodeEntity {

    ...

    @Relationship(type="OWNS")
    private Set<Dog> dogs; // both dog and cat are mapped here

    @Relationship(type="OWNS")
    private Set<Cat> cats; // both dog and cat are mapped here

    ...
}

spring-data-neo4j-4 フレームワークは、Dog と Cat の両方を Cats のセットと Dogs のセットに自動的にマップするため、2 つの「犬」(実際にはそのうちの 1 つが猫ですが) と 2 つの「データベースからロードされた猫 (ただし、そのうちの 1 つは実際には犬です)。データ モデルからスーパー クラス Pet と BaseNodeEntity を削除すると、Dog と Cat はそれぞれのセットに自動的に正しくマップされます。

spring-data-neo4j-4 にデータ モデルを正しくマッピングさせる方法はありますか? または、データ モデルを強制的に変更する必要がありますか? 多くの再利用が行われているため、データ モデルからスーパー クラスを削除することに熱心ではありません。余分な関係を追加する (つまり、OWNS を CAT_OWNER と DOG_OWNER に分割する) ことも同様に面倒です。

アップデート

この動作に一貫性がないことに気付きました。マッピングをテストする単体テストを作成しました。奇妙なことに、成功することもあれば失敗することもあります (誤って猫を犬として、犬を猫としてマッピングすることもあれば、そうでないこともあります)。単体テストを手動で 10 回実行すると、次の合格/不合格の結果が得られました。

Run, Result (pass / fail)
1   P
2   F
3   F
4   P
5   F
6   P
7   F
8   F
9   P
10  F

確かに、マッピングの動作は一貫している必要があります。これは SDN-4 のバグでしょうか?

2016 年 5 月 8 日更新

この度は更新が滞り申し訳ございません。私はこのプロジェクトに再び取り組む機会を得たばかりです。これを再テストしたところ、最新の安定した neo4j リリースで同じ結果が得られました。

<neo4j.version>2.3.2</neo4j.version>
<sdn.version>4.1.1.RELEASE</sdn.version>
<java.version>1.8</java.version>
<neo4j-ogm.version>2.0.1</neo4j-ogm.version>
<spring-data-commons.version>1.12.1.RELEASE</spring-data-commons.version>

テスト ケースで使用された実際のドメイン モデルを下に添付しました。テスト ケースの詳細は、 https://github.com/johndeverall/thescene-spa/issues/142で確認できます。テスト ケース コードは次のとおりです。

    @Test
    public void saveAndLoadTags() { 
        log.info("Given we have a member with some events");
        Member member = createMember();
        Event event1 = eventService.createEvent("Event1", member);
        Event event2 = eventService.createEvent("Event2", member);

        log.info("When I tag my events with some tags");
        contentService.tag("Tag1", "", event1, member);
        contentService.tag("Tag1", "", event1, member); // should create no new tags or relationships
        contentService.tag("Tag2", "", event1, member);
        contentService.tag("Tag2", "", event2, member);

        log.info("Then my events should be appropriately tagged");
        event1 = eventService.loadEventBySceneId(event1.getSceneId());
        assertThat(event1.getTags().size(), is(equalTo(2)));
        assertThat(event2.getTags().size(), is(equalTo(1)));

        log.info("And I should have created two tags total");
        Iterator<Tag> iterator = contentService.getAllTags().iterator();
        List<Tag> tags = StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.ORDERED), false).collect(Collectors.<Tag> toList());
        assertThat(tags.size(), is(equalTo(2)));

        log.info("And our member should have created two tags");
        member = memberService.loadMemberByEmailAddressPasswordAccount(emailAddress);

        // **************************************************************
        // member.getCreatedTags().size() more often than not returns 3   causing my test failure!
        // **************************************************************
        assertThat(member.getCreatedTags().size(), is(equalTo(2)));
    }

テストケースが示す問題

次の方法:

public Member loadMemberByEmailAddressPasswordAccount(String emailAddress) { 
        Filter filter = new Filter("email", emailAddress);
        Collection<EmailAddressPasswordAccount> emailAddressPasswordAccounts = session.loadAll(EmailAddressPasswordAccount.class, filter, 2);
        return emailAddressPasswordAccounts.isEmpty() ? null : emailAddressPasswordAccounts.iterator().next().getMember();
    }

2 つのタグと、実際にはイベントであるタグを含む、createdTags のセットを持つメンバー オブジェクトを返します。

私の実際のドメイン モデルは以下のとおりです (Dogs and Cats に簡略化されていません)。

OGM図

追加情報:

@NodeEntity アノテーションを使用して、BaseNodeEntity 以外のすべてのモデル オブジェクトにアノテーションを付けてみました。プロパティには注釈が付けられます。

2016 年 5 月 9 日更新

loadMemberByEmailAddressPasswordAccount の ogm コードをリポジトリの派生ファインダーと交換すると、同じ断続的な結果が得られます。

4

1 に答える 1