1

The test below fails if I remove the first persist(). Why do I need to persist the NodeEntity in order for the Set to be instantiated? Is there some better way to do this? I don't want to have to write to the database more often than nessesary.

 @Test
public void testCompetenceCreation() {
    Competence competence = new Competence();
    competence.setName("Testcompetence");
    competence.persist(); //test fails if this line is removed
    Competence competenceFromDb = competenceRepository.findOne(competence.getId());

    assertEquals(competence.getName(), competenceFromDb.getName());

    Education education = new Education();
    education.setName("Bachelors Degree");
    competence.addEducation(education);
    competence.persist();


    assertEquals(competence.getEducations(), competenceFromDb.getEducations());
}

If i remove the mentioned line, the exception bellow occurs:

Throws

java.lang.NullPointerException
at com.x.entity.Competence.addEducation(Competence.java:54)

Competence.class:

@JsonIgnoreProperties({"nodeId", "persistentState", "entityState"})
@NodeEntity
public class Competence {

    @RelatedTo(type = "EDUCATION", elementClass = Education.class)
    private Set<Education> educations;

    public Set<Education> getEducations() {
        return educations;
    }

    public void addEducation(Education education) {
        this.educations.add(education);
    }
}

Education.class

@JsonIgnoreProperties({"nodeId", "persistentState", "entityState"})
@NodeEntity
public class Education {

    @GraphId
    private Long id;

    @JsonBackReference
    @RelatedTo(type = "COMPETENCE", elementClass = Competence.class, direction = Direction.INCOMING)
    private Competence competence;

    @Indexed
    private String name;

    public Long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
Soroush Hakami
  • 5,226
  • 15
  • 66
  • 99

1 Answers1

1

What version of SDN are you running?

Because up until the first persist the entity is detached and AJ doesn't take care of the fields (like creating the managed set). Persist creates the node at connects it to the entity, from then on until the transaction commits your entity is attached and all the changes will be written through.

It only writes to the db at commit, so no worries about too many writes. All the other changes will just be held in memory for your transaction. Probably you should also annotate the test method with @Transactional.

Can you create a JIRA issue for this? So that a consistent handling is provided. (Problem being that it probably also complains when you initialize the set yourself.)

Two other things:

  • as your relationship between Education<--Competence is probably the same and should just be navigated in the other direction you must provide the same type name in the annotation.
  • e.g. Education<-[:PROVIDES]-Competence

  • also if you don't call persist your entity will not be created and then the findOne by returning null

Michael Hunger
  • 41,339
  • 3
  • 57
  • 80
  • Thanks for your quick reply Michael. I now understand how I need to use persist, and you were also right on your note on the relationship type in the annotation. Could you explain what you want me to write in the Jira-issue though? Since as I understand it, this is no bug but rather me not having a complete understanding of the way Spring Data Graph works :-) – Soroush Hakami Nov 11 '11 at 14:18
  • Just create the issue and link it to this discussion. As description add - initialize collection fields in a consistent way. Thanks – Michael Hunger Nov 18 '11 at 05:07
  • Done! Again, thanks for your help, much appreciated. https://jira.springsource.org/browse/DATAGRAPH-135 – Soroush Hakami Nov 18 '11 at 07:47