Announcement Announcement Module
Collapse
No announcement yet.
Spring Data Neo4j - Handling simple objects as NodeEntity properties Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Spring Data Neo4j - Handling simple objects as NodeEntity properties

    Hi,

    I'm just playing around with spring-data neo4j ... Suppose I have a Profile class containing a set of Address
    @NodeEntity
    class Profile {
    @GraphId Long id;
    String name;
    Set<Address> addresses;
    }
    class Address {
    String doorNumber;
    String street;
    String city;
    }
    I want to be able to build a Profile object, and using a ProfileRepository, call repository.save(myProfile) and have the addresses automatically saved. But Address is a simple object. Do I have to make Address an NodeEntity and give it an ID property ? I tried it and when I get back the Profile object back from the repository, there is one address in the list and all the fields are null except ID.

    What are my options ?

    Thanks

  • #2
    You can add a Spring-Converter to your spring config which is able to convert between Address and String e.g to JSON.
    Code:
    // Could be either a GenericConverter or a Converter<Address,String> + Converter<String,Address>
    
    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
            <property name="converters">
                <set>
                    <bean class="org.example.converter.AddressToStringConverter"/>
                </set>
            </property>
        </bean>
    Michael

    Comment


    • #3
      Thanks Michael.
      I will try the conversion solution, but I still have a problem using both classes (Profile, Address) as NodeEntities. The case is simpler now, Profile only contains one Address annotated with @RelatedTo.
      @NodeEntity
      class Profile {
      @GraphId Long id;
      String name;
      @RelatedTo
      Address address;
      }
      @NodeEntity
      class Address {
      @GraphId Long id;
      String doorNumber;
      String street;
      String city;
      }
      If I retrieve a profile by id and call profile.getAddress, the Address returned only have the id property set, everything else is null. If I retrieve the Address object directly by id using the AddressRepository, all the data is there. It's working fine in the advanced aspectj mode, but when using the simpler pojo mode, I get a bunch of null fields. Any thoughts ?

      Comment


      • #4
        I created a small project with a test to illustrate the problem.

        https://github.com/dreamagex/neo4j-profileaddress-test

        Comment


        • #5
          If you use simple mapping mode, you have to add @Fetch to the Address or the Collection<Address> field to be loaded eagerly.

          Sorry for not seeing that as the issue immediately.


          Michael

          Comment


          • #6
            I thought the address field would have been replaced with a proxy for lazy loading ? Because the way I see it, if you don't put @Fetch on a field, it's pretty useless, isn't it ?

            Comment


            • #7
              I didn't want to go into the ugly realm of lazy proxies.

              You can always load those objects/collections with template.fetch() later if you need them.

              Michael

              Comment


              • #8
                You know, I have tried template.fetch before and that didn't load my associated objects. I had to do a separate Cypher query to get the associated objects myself.

                Mark

                Comment


                • #9
                  Do you have a test-case for that?

                  It should do it.

                  Michael

                  Comment


                  • #10
                    I updated my example with Neo4jTemplate.fetch and it's working just fine. Thanks Michael.

                    Comment


                    • #11
                      Michael, quick question ...

                      Where do you suggest I keep the Neo4jTemplate object. I cannot pass it in the object constructor to a transient private variable since we need a no-arg constructor, and passing it to a getter kind of leaks the db abstraction through my API. Any suggestion ?

                      Comment


                      • #12
                        You probably don't need it inside of your methods, the simple save() operation cascades at least to relationship-objects.

                        Could you handle this as part of a service? So you can persist the actual relationship-entities before they are added to the collection which might be good enough, depending on your use-case.

                        Michael

                        Comment


                        • #13
                          Originally posted by MichaelHunger View Post
                          Do you have a test-case for that?

                          It should do it.

                          Michael
                          Sorry, no test case.

                          After I saw that I wasn't retrieved the related nodes with fetch, I went down a separate path where I first get the top level Node then on the client side page I use AJAX to $.get() each collection as JSON and update the page when the JSON comes back. this way I can have 7 different .gets happening simultaneously to get all the collection nodes. And even yesterday I decided to restructure my page, so now I get a list of wrapper objects. no nodes for even less data being transferred. I will just write a nice complex traversal query to get just what I need on the first .get request. (Except for the index.jsp with no data, all my requests are REST Ajax JSON from client to server)

                          Thanks

                          Mark

                          Comment

                          Working...
                          X