2

In my Neo4j 3.0.1 and SDN 4.1.1.RELEASE project I have a following entities:

@NodeEntity
public class CriterionGroup extends Authorable {

    private final static String DEFINED_BY = "DEFINED_BY";
    private final static String CONTAINS = "CONTAINS";

    private String name;

    private String description;

    @Relationship(type = DEFINED_BY, direction = Relationship.OUTGOING)
    private Decision owner;

    @Relationship(type = CONTAINS, direction = Relationship.OUTGOING)
    private Set<Criterion> criteria = new HashSet<>();
....

@NodeEntity
public class Criterion extends Authorable {

    private final static String CONTAINS = "CONTAINS";
    private final static String DEFINED_BY = "DEFINED_BY";

    private String name;

    private String description;

    @Relationship(type = CONTAINS, direction = Relationship.INCOMING)
    private CriterionGroup group;

    @Relationship(type = DEFINED_BY, direction = Relationship.OUTGOING)
    private Decision owner;
....


@NodeEntity
public class Decision extends Commentable {

    private final static String CONTAINS = "CONTAINS";
    private final static String DEFINED_BY = "DEFINED_BY";
    private final static String VOTED_FOR = "VOTED_FOR";

    private String name;

    @Relationship(type = CONTAINS, direction = Relationship.INCOMING)
    private Set<Decision> parentDecisions = new HashSet<>();

    @Relationship(type = CONTAINS, direction = Relationship.OUTGOING)
    private Set<Decision> childDecisions = new HashSet<>();

    @Relationship(type = DEFINED_BY, direction = Relationship.INCOMING)
    private Set<CriterionGroup> criterionGroups = new HashSet<>();

    @Relationship(type = DEFINED_BY, direction = Relationship.INCOMING)
    private Set<Criterion> criteria = new HashSet<>();
....

In my test I'm trying to delete CriterionGroup with a following repository method:

@Query("MATCH ()-[r]-(cg:CriterionGroup) WHERE id(cg) = {criterionGroupId} DELETE cg, r")
void deleteCriterionGroup(@Param("criterionGroupId") Long criterionGroupId);

then I'm trying to get this CriterionGroup by id

criterionGroupRepository.findOne(id);

and it returns NULL. So far so good.

Right after that I'm trying to get group object from Criterion that was in the deleted CriterionGroup and it returns.. deleted CriterionGroup

criterionRepository.findOne(criterion.getId()).getGroup()

What am I doing wrong ? Everything worked fine on SDN 3.4.4.RELEASE and Neo4j 2.3.3 but with Neo4j 3.0.1 SDN 4.1.1.RELEASE due to my limited knowledge I have a lot of unexpected situations.

Also, Is it okay to have a following relationship definition in a one entity(I have removed enforceTargetType )

@Relationship(type = CONTAINS, direction = Relationship.INCOMING)
private Set<Decision> parentDecisions = new HashSet<>();

@Relationship(type = CONTAINS, direction = Relationship.OUTGOING)
private Set<Decision> childDecisions = new HashSet<>();

they have different directions.

Luanne
  • 19,145
  • 1
  • 39
  • 51
brunoid
  • 2,121
  • 2
  • 12
  • 22

1 Answers1

2

As far as I can tell, you're having this CriterionGroup re-appear because you deleted it via a custom query, thus bypassing the OGM. The graph knows of your change, but the OGM's mapping context does not. The solution is to deregister this entity from the session after you've deleted it via a custom query using Session.detachEntity(id), or, refresh the entire session with session.clear().

Yes, it is okay to have the CONTAINS relationship definitions, please remember that for any relationship marked INCOMING, you must annotate accessors, mutators and properties for parentDecisions if they exist with @Relationship(type = CONTAINS, direction = Relationship.INCOMING)

Update: Also make sure your object model is in sync with what you're deleting via custom query. i.e. if you're deleting the CriterionGroup via a custom query, you should also update your object model to reflect this i.e. criterion.group=null. Or, clear your session completely using session.clear() and reload all dependent entities.

Luanne
  • 19,145
  • 1
  • 39
  • 51
  • Thanks for your answer. What is the proper way for getting a reference to Session object ? Also, for `Decision.parentDecisoins` I have a following methods - `Set getParentDecisions()`, `addParentDecision(Decision decision)`, `removeParentDecision(Decision decision)`.. should all of them also be annotated with `@Relationship(type = CONTAINS, direction = Relationship.INCOMING)` ? If so, why do we need such kind of redundancy ? – brunoid May 25 '16 at 12:30
  • I found a way how to access Session. But `session.detachNodeEntity(criterionGroupId);` doesn't work. But `session.clear();` clears all other objects also so all of my existing tests fail. – brunoid May 25 '16 at 12:55
  • Also, do you have a plans to automatically synchronize the state between OGM and custom Cypher query execution ? – brunoid May 25 '16 at 14:27
  • Just the add and get. We'll be revisiting some of the mapping rules in the near future so this should be simplified then. No plans right now to sync state between the ogm and custom queries. Clearing the session should not have affected your tests. When you say detachNodeEntity does not work do you mean you still get the spurious relationship back? – Luanne May 25 '16 at 16:05
  • Yeah, after this method invocation `@Override public void deleteCriterionGroup(Long criterionGroupId) { criterionGroupRepository.deleteCriterionGroup(criterionGroupId); session.detachNodeEntity(criterionGroupId); }` I'm still getting the deleted node back in my test assertion `assertNull(criterionDao.findById(horScalingCriterion.getId()).getGroup());` ... via a reference from another node – brunoid May 25 '16 at 17:07
  • I'm injecting Session into my Spring DAO via `@Autowired private Session session;` – brunoid May 25 '16 at 17:14
  • @brunoid perhaps find us on neo4j-users.slack.com - easier to discuss this via chat – Luanne May 26 '16 at 06:59
  • Thanks, I have sent message to you via slack – brunoid May 26 '16 at 11:16