Announcement Announcement Module
Collapse
No announcement yet.
Inheritance in spring-data-neo4j Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • 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
    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

    Comment


    • #3
      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

      Comment


      • #4
        I created the issue https://jira.springsource.org/browse/DATAGRAPH-145

        Comment


        • #5
          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

          Comment


          • #6
            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

            Comment


            • #7
              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

              Comment


              • #8
                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.

                Comment


                • #9
                  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

                  Comment


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

                    Comment


                    • #11
                      For completeness: http://forum.springsource.org/showth...ing-Data-Neo4j

                      Thanks Eugen!

                      Comment

                      Working...
                      X