You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@geode.apache.org by Pieter van Zyl <pi...@lautus.net> on 2018/02/06 09:15:22 UTC

How does Apache Geode handle one-to-one and one-to-many relationships?

Good day.

We are investigating Geode to replace our current database solution.

I would like to understand how Geode handles relationships.

I hope I am posting to the right forum as this relates to fundamentals in
Geode but I am using the Spring Data Geode examples.

Overall it seems to me that one-to-one or one-to-many relationships are
stored embedded into the "parent" region.

If  Parent has a list of Children then it seems that there are 2 options in
Geode:

   - Use id's that refer to the child entities. Child entities are then
   stored in its own region.
   - Direct reference to the Children. In JPA that would have been called a
   one-to-many mapping. But this will be stored locally in the same region as
   the Parent.

I can see some examples using either id's or one-to-one or one-to-many
relationships here:
https://github.com/spring-projects/spring-gemfire-examples

Specifically: spring-gemfire-examples-master/basic/persistence which uses
an Order that has an Address (one-to-one). Order also has a list to
LineItems that contains an id that represents the actual Product which is
an example of one-to-many.

*I would like to confirm that as Geode is a key-value store that one would
need to represent one-to-one and  one-to-many relationships using the id's
and then look them up to get the actual associated objects?*

I did read this nice response here as well:
https://stackoverflow.com/questions/37908733/data-model-design-guide-lines-with-geode/37931066#37931066

I just want to clearly understand using a example that speaks directly to
relationships.

In the example below I can see that if I don't use id's that the child
objects get *stored twice*: in the Child region *as well also
local/embedded* with the Parent.

/**
     * This test shows that Geode store references to embedded one-to-one
entities locally to the parent object and then it can only see
     * changes via the parent object and wont see changes made to the child
that are stored in other regions
     */
    @Test
    public void testChildAddedToOwnRegion() {
        Parent parent = new Parent(2l, "Pvz");

        Child child1 = new Child(5l, "Child1", parent);
        childRepository.save(child1);

        Child child2 = new Child(6l, "Child2", parent);
        childRepository.save(child2);

        Child child3 = new Child(7l, "Child3", parent);
        childRepository.save(child3);

        parent.getChildren().add(child1);
        parent.getChildren().add(child2);
        parent.getChildren().add(child3);

        log.info("Parent: " + parent.getId());

        parentRepository.save(parent);

        log.info("Parent: " + parent.getId());

        Parent foundParent1 = parentRepository.findById(2l).get();
        log.info("foundParent1: " + foundParent1.getChildren().size());

        List<Child> children = (List<Child>) childRepository.findAll();

        log.info("Children found: " + children.size());
        Assert.assertEquals(3, children.size());

        Child child = childRepository.findById(5l).get();
        Assert.assertNotNull(child);
        Assert.assertEquals("Child1", child.getName());
        child.setName("Child5");
        childRepository.save(child);

        foundParent1 = parentRepository.findById(2l).get();
        List<Child> children1 = foundParent1.getChildren();

        boolean found = false;

        for (Child ch : children1) {

            if (ch.getName().equals("Child5")) {
                found = true;
            }
            log.info(ch.getName());
        }
        Child childFound = childRepository.findById(5l).get();
        Assert.assertEquals("Child5", child.getName());
        Assert.assertFalse(found);
    }

Kindly
Pieter van Zyl
Lautus Solutions
South Africa

Re: How does Apache Geode handle one-to-one and one-to-many relationships?

Posted by Pieter van Zyl <pi...@lautus.net>.
Hi Udo

Thanks for confirming this for me.

Btw, we have a framework very similar to Hibernate OGM that can take an
object domain model and map it transparently to a key value store.
We have now added Geode and looking at splitting out the one-to-one
(embedded) objects as well. Already have logic for the 1:M and M:N

Still early days and we need to look at performance and if this is the
right way. A lot more thought as you say still need to happen.

Maybe in the future we could partner on this as an "Hibernate" like layer
on Geode...

Thanks again for the quick and clear response.

Kindly
Pieter



On Tue, Feb 6, 2018 at 9:27 PM, Udo Kohlmeyer <uk...@pivotal.io> wrote:

> Hi there Pieter.
>
> Geode does not manage any relationships like 1:1, 1:M or even M:N.
>
> Your observations, from your example, are correct. The child will be
> stored twice (once in the parent region and once in the child region).
> You've already reached a correct conclusion that the relationships are
> better maintained by referencing the parent/child via their respective keys.
>
> This of course has an additional overhead where you need to modify the
> parent every time you add/remove a child. Storing it in that manner has the
> benefit that your parent does not become a large object, as more and more
> child obj's are added.
>
> A "nice" feature would be to implicitly be able to define the
> relationships and then the underlying storage mechanism handles the
> normalized storage (like hibernate would do). But this feature does still
> require more thought.
>
> --Udo
>
>
> On Tue, Feb 6, 2018 at 1:15 AM, Pieter van Zyl <pi...@lautus.net>
> wrote:
>
>> Good day.
>>
>> We are investigating Geode to replace our current database solution.
>>
>> I would like to understand how Geode handles relationships.
>>
>> I hope I am posting to the right forum as this relates to fundamentals in
>> Geode but I am using the Spring Data Geode examples.
>>
>> Overall it seems to me that one-to-one or one-to-many relationships are
>> stored embedded into the "parent" region.
>>
>> If  Parent has a list of Children then it seems that there are 2 options
>> in Geode:
>>
>>    - Use id's that refer to the child entities. Child entities are then
>>    stored in its own region.
>>    - Direct reference to the Children. In JPA that would have been
>>    called a one-to-many mapping. But this will be stored locally in the same
>>    region as the Parent.
>>
>> I can see some examples using either id's or one-to-one or one-to-many
>> relationships here:
>> https://github.com/spring-projects/spring-gemfire-examples
>>
>> Specifically: spring-gemfire-examples-master/basic/persistence which
>> uses an Order that has an Address (one-to-one). Order also has a list to
>> LineItems that contains an id that represents the actual Product which is
>> an example of one-to-many.
>>
>> *I would like to confirm that as Geode is a key-value store that one
>> would need to represent one-to-one and  one-to-many relationships using the
>> id's and then look them up to get the actual associated objects?*
>>
>> I did read this nice response here as well:
>> https://stackoverflow.com/questions/37908733/data-model-desi
>> gn-guide-lines-with-geode/37931066#37931066
>>
>> I just want to clearly understand using a example that speaks directly to
>> relationships.
>>
>> In the example below I can see that if I don't use id's that the child
>> objects get *stored twice*: in the Child region *as well also
>> local/embedded* with the Parent.
>>
>> /**
>>      * This test shows that Geode store references to embedded one-to-one
>> entities locally to the parent object and then it can only see
>>      * changes via the parent object and wont see changes made to the
>> child that are stored in other regions
>>      */
>>     @Test
>>     public void testChildAddedToOwnRegion() {
>>         Parent parent = new Parent(2l, "Pvz");
>>
>>         Child child1 = new Child(5l, "Child1", parent);
>>         childRepository.save(child1);
>>
>>         Child child2 = new Child(6l, "Child2", parent);
>>         childRepository.save(child2);
>>
>>         Child child3 = new Child(7l, "Child3", parent);
>>         childRepository.save(child3);
>>
>>         parent.getChildren().add(child1);
>>         parent.getChildren().add(child2);
>>         parent.getChildren().add(child3);
>>
>>         log.info("Parent: " + parent.getId());
>>
>>         parentRepository.save(parent);
>>
>>         log.info("Parent: " + parent.getId());
>>
>>         Parent foundParent1 = parentRepository.findById(2l).get();
>>         log.info("foundParent1: " + foundParent1.getChildren().size());
>>
>>         List<Child> children = (List<Child>) childRepository.findAll();
>>
>>         log.info("Children found: " + children.size());
>>         Assert.assertEquals(3, children.size());
>>
>>         Child child = childRepository.findById(5l).get();
>>         Assert.assertNotNull(child);
>>         Assert.assertEquals("Child1", child.getName());
>>         child.setName("Child5");
>>         childRepository.save(child);
>>
>>         foundParent1 = parentRepository.findById(2l).get();
>>         List<Child> children1 = foundParent1.getChildren();
>>
>>         boolean found = false;
>>
>>         for (Child ch : children1) {
>>
>>             if (ch.getName().equals("Child5")) {
>>                 found = true;
>>             }
>>             log.info(ch.getName());
>>         }
>>         Child childFound = childRepository.findById(5l).get();
>>         Assert.assertEquals("Child5", child.getName());
>>         Assert.assertFalse(found);
>>     }
>>
>> Kindly
>> Pieter van Zyl
>> Lautus Solutions
>> South Africa
>>
>
>

Re: How does Apache Geode handle one-to-one and one-to-many relationships?

Posted by Udo Kohlmeyer <uk...@pivotal.io>.
Hi there Pieter.

Geode does not manage any relationships like 1:1, 1:M or even M:N.

Your observations, from your example, are correct. The child will be stored
twice (once in the parent region and once in the child region).
You've already reached a correct conclusion that the relationships are
better maintained by referencing the parent/child via their respective keys.

This of course has an additional overhead where you need to modify the
parent every time you add/remove a child. Storing it in that manner has the
benefit that your parent does not become a large object, as more and more
child obj's are added.

A "nice" feature would be to implicitly be able to define the relationships
and then the underlying storage mechanism handles the normalized storage
(like hibernate would do). But this feature does still require more thought.

--Udo


On Tue, Feb 6, 2018 at 1:15 AM, Pieter van Zyl <pi...@lautus.net>
wrote:

> Good day.
>
> We are investigating Geode to replace our current database solution.
>
> I would like to understand how Geode handles relationships.
>
> I hope I am posting to the right forum as this relates to fundamentals in
> Geode but I am using the Spring Data Geode examples.
>
> Overall it seems to me that one-to-one or one-to-many relationships are
> stored embedded into the "parent" region.
>
> If  Parent has a list of Children then it seems that there are 2 options
> in Geode:
>
>    - Use id's that refer to the child entities. Child entities are then
>    stored in its own region.
>    - Direct reference to the Children. In JPA that would have been called
>    a one-to-many mapping. But this will be stored locally in the same region
>    as the Parent.
>
> I can see some examples using either id's or one-to-one or one-to-many
> relationships here:
> https://github.com/spring-projects/spring-gemfire-examples
>
> Specifically: spring-gemfire-examples-master/basic/persistence which uses
> an Order that has an Address (one-to-one). Order also has a list to
> LineItems that contains an id that represents the actual Product which is
> an example of one-to-many.
>
> *I would like to confirm that as Geode is a key-value store that one would
> need to represent one-to-one and  one-to-many relationships using the id's
> and then look them up to get the actual associated objects?*
>
> I did read this nice response here as well:
> https://stackoverflow.com/questions/37908733/data-model-
> design-guide-lines-with-geode/37931066#37931066
>
> I just want to clearly understand using a example that speaks directly to
> relationships.
>
> In the example below I can see that if I don't use id's that the child
> objects get *stored twice*: in the Child region *as well also
> local/embedded* with the Parent.
>
> /**
>      * This test shows that Geode store references to embedded one-to-one
> entities locally to the parent object and then it can only see
>      * changes via the parent object and wont see changes made to the
> child that are stored in other regions
>      */
>     @Test
>     public void testChildAddedToOwnRegion() {
>         Parent parent = new Parent(2l, "Pvz");
>
>         Child child1 = new Child(5l, "Child1", parent);
>         childRepository.save(child1);
>
>         Child child2 = new Child(6l, "Child2", parent);
>         childRepository.save(child2);
>
>         Child child3 = new Child(7l, "Child3", parent);
>         childRepository.save(child3);
>
>         parent.getChildren().add(child1);
>         parent.getChildren().add(child2);
>         parent.getChildren().add(child3);
>
>         log.info("Parent: " + parent.getId());
>
>         parentRepository.save(parent);
>
>         log.info("Parent: " + parent.getId());
>
>         Parent foundParent1 = parentRepository.findById(2l).get();
>         log.info("foundParent1: " + foundParent1.getChildren().size());
>
>         List<Child> children = (List<Child>) childRepository.findAll();
>
>         log.info("Children found: " + children.size());
>         Assert.assertEquals(3, children.size());
>
>         Child child = childRepository.findById(5l).get();
>         Assert.assertNotNull(child);
>         Assert.assertEquals("Child1", child.getName());
>         child.setName("Child5");
>         childRepository.save(child);
>
>         foundParent1 = parentRepository.findById(2l).get();
>         List<Child> children1 = foundParent1.getChildren();
>
>         boolean found = false;
>
>         for (Child ch : children1) {
>
>             if (ch.getName().equals("Child5")) {
>                 found = true;
>             }
>             log.info(ch.getName());
>         }
>         Child childFound = childRepository.findById(5l).get();
>         Assert.assertEquals("Child5", child.getName());
>         Assert.assertFalse(found);
>     }
>
> Kindly
> Pieter van Zyl
> Lautus Solutions
> South Africa
>