Wolfgang-Schuetzelhofer / jcypher

Java access to Neo4J graph databases at multiple levels of abstraction
Apache License 2.0
86 stars 15 forks source link

[Domain Mapping] Reference incoming relations #7

Closed nicoruti closed 9 years ago

nicoruti commented 9 years ago

Hi Wolfgang

I'm running some experiment with your library and am enjoying it's simplicity. I created a mapping that looks as follows:

(Person)-[worksFor]->(Company)

Therefore, I created the two classes. The Person keeps a reference to the company. However, is it possible to keep a reference to all employees in the Company class? If I use the following code, there mapper creates something like

(p:Person)-[worksFor]->(Company)-[employees]->(Collection)-[c_content]->(p)

public class Person {
   public String name;
   public Company worksFor;
}

public class Company {
   public String name;
   public List<Person> employees; // --> should be same relation as Person#worksFor
}

Small test method:

@Test
public void testIncomingRelation() {
    // arrange
    Company company = new Company();
    company.name = "Google";
    Person person = new Person();
    person.name = "Tom";
    person.worksFor = company;
    company.employees = Arrays.asList(person);

    // act
    domainAccess.store(person);
    Company retrievedComp = domainAccess.loadById(Company.class, 1, domainAccess.getSyncInfo(company).getId());

    // assert
    assertThat(retrievedComp.employees, contains(person));
   }
Wolfgang-Schuetzelhofer commented 9 years ago

Hi Nico,

JCypher, when it maps Java Object Graphs to Neo4J, maps a List or an Array to a distinct node (that's what you see). This is intentional, as Lists and Arrays are themselfes objects in Java. It is possible that 2 or more objects hold references to the same List instance. So when you change the content of the List, that is reflected in all objects which hold references to this List. When JCypher reads Java Object Graphs from a Neo4j database it must be able to restore exactly that state (multiple objects referencing the same list). This is only possible when the List itself is explicitly represented in the Neo4j Graph.

Hope that helps, best regards, Wolfgang

-----Original Message----- From: Nico Rutishauser notifications@github.com To: Wolfgang-Schuetzelhofer/jcypher jcypher@noreply.github.com Sent: Tue, Oct 20, 2015 2:46 pm Subject: [jcypher] [Domain Mapping] Reference incoming relations (#7)

Hi Wolfgang I'm running some experiment with your library and am enjoying it's simplicity. I created a mapping that looks as follows: (Person)-[worksFor]->(Company) Therefore, I created the two classes. The Person keeps a reference to the company. However, is it possible to keep a reference to all employees in the Company class? If I use the following code, there mapper creates something like (p:Person)-[worksFor]->(Company)-[employees]->(Collection)-[c_content]->(p) public class Person { public String name; public Company worksFor; }

public class Company { public String name; public List employees; // --> should be same relation as Person#worksFor }

Small test method: @Test public void testIncomingRelation() { // arrange Company company = new Company(); company.name = "Google"; Person person = new Person(); person.name = "Tom"; person.worksFor = company; company.setEmployees(Arrays.asList(person));

// act
domainAccess.store(person);
Company retrievedComp = domainAccess.loadById(Company.class, 1, domainAccess.getSyncInfo(company).getId());

// assert
assertThat(retrievedComp.getEmployees(), contains(person));

}

— Reply to this email directly or view it on GitHub.

nicoruti commented 9 years ago

Hi Wolfgang

Right, got your point! I was coming from the OGM project, where one can declare relations using annotations. But as JCypher works without annotations, there's no way around having an own node for the collection, as you explained nicely.