Page 1 of 2 12 LastLast
Results 1 to 10 of 11

Thread: Inheritance in spring-data-neo4j

  1. #1
    Join Date
    Nov 2011
    Posts
    8

    Default Inheritance in spring-data-neo4j

    Hi,

    I'm using spring-data-neo4j in an object model with inheritance, with a base class Video, a subclass YoutubeVideo and a VideoRepository. The Video base class contains a field "id", which uses @Indexed

    When I save a Video instance with an id field a call to VideoRepository.findById returns the object.

    However, if I save a YoutubeVideo, the same call to VideoRepository.findById returns null.

    Why do I get a different behavior here?

    Here are the model classes:


    @NodeEntity
    public class Video {
    @GraphId
    public Long nodeId;
    @Indexed
    public String id;
    @Indexed
    public String title;
    public String description;
    public String originalTitle;
    public String thumbnailUrl;
    }
    public class YoutubeVideo extends Video {
    public String youtubeId;
    }

    public interface VideoRepository extends GraphRepository<Video>, NamedIndexRepository<Video>,
    RelationshipOperationsRepository<Video> {
    Video findById(String id);
    }



    Here is the test code I use. The second test fails.

    @Test
    public void findVideo() {
    Video video = new Video();
    video.setId("test.new");

    videoRepository.save(video);
    Video existing = videoRepository.findById(video.getId());
    assertNotNull(existing);

    videoRepository.delete(existing);
    existing = videoRepository.findById(video.getId());
    assertNull(existing);
    }

    @Test
    public void findVideoSubclass() {
    YoutubeVideo video = new YoutubeVideo();
    video.setId("test.subclass");

    videoRepository.save(video);
    Video existing = videoRepository.findById(video.getId());
    assertNotNull(existing); <--------- fails

    videoRepository.delete(existing);
    existing = videoRepository.findById(video.getId());
    assertNull(existing);
    }

  2. #2
    Join Date
    Jan 2011
    Location
    Dresden, Germany
    Posts
    525

    Default

    If you use videoRepository.findById() it only looks on the video-repository level (as it only knows about that). It creates a cypher query that uses:

    start n = node:Video(id={0}) return n;

    There is the @Indexed(level=IndexType.INSTANCE) attribute that makes the field being indexed at the instance-class level and not at the level of the declaring class of the field. I'm just thinking about adding another option that says IndexType.HIERARCHY that adds an index-entry on all levels.

    Could you please raise a JIRA issue for this.

    Thanks a lot

    Michael

  3. #3
    Join Date
    Nov 2011
    Posts
    8

    Default

    Hi Michael,

    Thanks for your reply! While I guess I understand why it does happen here (it doesnt find the start node on the index for videos), I am not sure this should be a configurable behavior. For everybody coming from JPA and other object mapping solutions, this would be the expected behavior. Additionally, I saved the Video subclass through the VideoRepository - it's not like I am saving the Object through a YoutubeVideoRepository and retrieve it through a VideoRepository.

    BTW, while trying to figure out how spring-data-neo4j handles inheritance, I searched for a test that works with subclasses and repositories. While the test models in org.springframework.data.neo4j.model contain a model with a Car (abstract) base class and two subclasses Toyota and Volvo, they don't seem to be used in any test. Are there any tests that test inheritance with spring-data-neo4j?

    Finally, as I am new to cipher, is there any query that I could use to develop my application in the meantime that would give me the desired behavior as a workaround?

    Best,

    Nils

  4. #4
    Join Date
    Nov 2011
    Posts
    8

  5. #5
    Join Date
    Jan 2011
    Location
    Dresden, Germany
    Posts
    525

    Default

    Nils,

    Actually when thinking about it, it should find the start-node as the id field is on the Video class and you didn't specify anything else - that's why the JIRA issue would be helpful to track this.

    You can use cypher queries as annotations on repository methods:

    @Query("start n=node:Video(id={0}) return n")
    Video findById(String id);

    you can also query cypher directly via the template.query() methods

    there are also more generic index-lookup methods in the repository and template.

    out of my head:
    repo.findByPropertyValue("id",id);
    repo.findAllByPropertyValue("id",id);

    template.lookup(Video.class, "id", id).to(Video.class).singleOrNull();

    the car inheritance tree is currently used in the advanced-AJ-Mapping tests.

    You're right that has to be added to the simple mapping too, fell through the gap

    Could you add this to (another) JIRA issue?

    Thanks a lot for your help

    Michael

  6. #6
    Join Date
    Nov 2011
    Posts
    8

    Default

    Hi Michael,

    I added another issue https://jira.springsource.org/browse/DATAGRAPH-146.

    With your approval, I'd even like to raise https://jira.springsource.org/browse/DATAGRAPH-145 to priority critical. WDYT?

    Best,

    Nils

  7. #7
    Join Date
    Jan 2011
    Location
    Dresden, Germany
    Posts
    525

    Default

    Thanks Nils,

    please leave the prioritizing to me

    we have the GA release next week and I'm not sure it will make it in there. There are still a number of issues to be addressed and lots of docs to update

    Cheers

    Michael

  8. #8
    Join Date
    Nov 2011
    Posts
    8

    Default

    I understand, this is why I asked first ;-)

    BTW, I just added a diff to the issue with a test case. The derived query works when an index name is used on the index property, but fails if the property is indexed without an index name.

    So a workaround is to set the index name.

  9. #9
    Join Date
    Nov 2011
    Posts
    8

    Default

    Hi Michael,

    I am now running against another problem. While findById now finds the objects, it always returns objects of the base class type. Surprisingly, when I check the return type on the spring-data-neo4j tests I added (see diff uploaded at https://jira.springsource.org/browse/DATAGRAPH-145) everything seems to work. In my local code however, even after adding the constructors that take a Node as parameter, the method still returns the base class.

    Any pointers on that one?

    Best,

    Nils

  10. #10

    Default

    Any new development on this track? I'm running into very similar problems when doing some inheritance with neo4j and Spring Data.
    Thanks.
    Eugen.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •