Neo4j - Различающие отношения на основе типа подкласса конечного узла

Я заметил, что когда в модели данных spring-data-neo4j 4 используется наследование, суперкласс используется в качестве дискриминатора при загрузке и различении отношений на основе типа конечного узла. Есть ли способ заставить spring-data-neo4j-4 вместо этого использовать подкласс в качестве дискриминатора?

Например, предположим, что у нас есть модель данных (диаграмма классов), как показано ниже слева, и ее представление базы данных neo4j справа.

Диаграмма классов и представление neo4j

В настоящее время, если у нас есть сущность-владелец с кодом вроде:

@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, поэтому у меня есть две «собаки» (хотя одна из них на самом деле кошка) и две cats '(хотя одна из них на самом деле собака) загружены из базы данных. Если я удалю суперклассы 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?

Обновление от 8 мая 2016 г.

Приносим извинения за задержку с обновлением этого. У меня только что появилась возможность снова начать работу над этим проектом. Я повторно протестировал это и получаю те же результаты с последней стабильной версией 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/johndeshops/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();
    }

Возвращает объект-член, который имеет набор createdTags, содержащий 2 тега и тег, который на самом деле является событием.

Моя фактическая модель предметной области приведена ниже (не упрощенная для собак и кошек):

Схема OGM

Дополнительная информация:

Я пробовал аннотировать все объекты модели, кроме BaseNodeEntity, с помощью аннотации @NodeEntity. Свойства аннотированы.

Обновление от 9 мая 2016 г.

Я получаю такие же прерывистые результаты, если заменяю код ogm на loadMemberByEmailAddressPasswordAccount с производным средством поиска в репозитории.


person John Deverall    schedule 24.12.2015    source источник
comment
Спасибо за код, посмотрю   -  person Luanne    schedule 11.05.2016
comment
Я открыл github.com/neo4j/neo4j-ogm/issues/161   -  person Luanne    schedule 12.05.2016
comment
Спасибо, и спасибо за ваш код. Ты удивительный! :)   -  person John Deverall    schedule 12.05.2016


Ответы (1)


Вышеупомянутый случай, в котором использовались наборы отношений с одним и тем же типом, но с разными типами конечных узлов, был ошибкой: http://github.com/neo4j/neo4j-ogm/issues/161

Это было исправлено и доступно в Neo4j OGM 2.0.2.

person Luanne    schedule 28.12.2015
comment
Спасибо, Луанн! Мы включили новый выпуск в нашу последнюю сборку, и все наши внутренние тесты проходят сейчас :) - person John Deverall; 13.05.2016