Skip to content

Object mapping does not work correctly with abstract superclass and recursion #2138

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
rolevinks opened this issue Feb 9, 2021 · 6 comments
Assignees
Labels
type: bug A general bug

Comments

@rolevinks
Copy link

Hi, I'm using the version 6.0.3 of Spring Data Neo4j and I have a problem with retrieving a simple data structure with an abstract superclass and recursion. The problem is, that the objects are not mapped to their correct type.

This is the model:

@Node("Entity")
public abstract class Entity {
    @Id
    @GeneratedValue
    private Long id;

    @Relationship(type = "IS_CHILD")    
    private Entity parent;
}

@Node("Company")
public class Company extends Entity {

    private String name;   
}

@Node("Site")
public class Site extends Entity {

    private String name;   
}

@Node("Building")
public class Buildingextends Entity {

    private String name;   
}

// omitted getters and setters for brevity

The data structure I've created is

Building -IS_CHILD-> Site -IS_CHILD-> Company

I have defined a BuildingRepository:

@Repository
public interface BuildingRepository extends Neo4jRepository<Building, Long> {
}

When I retrieve the building with the findById, the building is retrieved correctly. However, its parent is incorrectly mapped as a building, and the parent of this is incorrectly mapped as a site (in all cases the name-field is mapped correctly).

Expected Behavior:
I expect buildingRepository.findById() to return the building with its correctly mapped parent, and their correctly mapped parent etc.

Actual Behavior:
The parent of the building and the parent of this parent are not mapped to the correct type. I think it has something to do with the labels; when instantiating the parent, the labels of the sourcenode are being used to derive the concrete node description for the parent.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Feb 9, 2021
@mrksph
Copy link

mrksph commented Feb 9, 2021

Hey, I have the same problem after trying to create an abstract class for what in principle was a concrete class

public abstract class BaseEntity {
    // Common fields among all domain entities (id, code, name, etc...)
    @Id
    @GeneratedValue
    private Long id;
    private String name;
}
// Abstract class that represents any kind of territory (Country, Continent, etc...)
@Node
public abstract class BaseTerritory extends BaseEntity{
   // Common fields among all territories. In this case the name in several languages: nameEn, nameEs
   private String nameEs;
   private String nameEn;
}
// Concrete class that represents a Generic Territory (
@Node
public class GenericTerritory extends BaseTerritory {}
//Concrete class for a Country 
@Node
public class Country extends BaseTerritory {
    private String countryProperty;
    
    @Relationship(type="LINK", direction=Relationship.Direction.OUTGOING)
    private Set<BaseTerritory> relationshipList = new HashSet<>();
}
// Concrete class for a Continent
@Node
public class Continent extends BaseTerritory {
    private String continentProperty;
}

If I do territoryRepository.findAll() every object is of the same type, even though I have some nodes of type Continent and others of type Country

Even more so, If I try to update a Country adding one item to its relationshipList it throws a org.springframework.dao.DataIntegrityViolationException

@myfrontpocket
Copy link

myfrontpocket commented Mar 3, 2021

I've also ran into this with a similar setup to OP. It kind of seems that the concrete implementation that is used is random, as opposed to being based on the actual, primary label (label 0) on the node in the DB.

@meistermeier meistermeier self-assigned this Mar 3, 2021
@meistermeier meistermeier added status: needs-investigation An issue that has been triaged but needs further investigation and removed status: waiting-for-triage An issue we've not yet triaged labels Mar 3, 2021
@meistermeier
Copy link
Collaborator

Thanks for reporting this. We are currently investigating the problem. I can confirm that this is a bug.

meistermeier added a commit that referenced this issue Mar 4, 2021
meistermeier added a commit that referenced this issue Mar 4, 2021
meistermeier added a commit that referenced this issue Mar 4, 2021
meistermeier added a commit that referenced this issue Mar 4, 2021
@meistermeier
Copy link
Collaborator

In a few minutes a 6.0.6-GH-2138-SNAPSHOT will appear in the snapshot repositories of Spring.
If you want, you could give it a try. I have taken your examples @rolevinks / @mrksph into the test base to ensure that I have not understood something wrong.

@meistermeier meistermeier added type: bug A general bug and removed status: needs-investigation An issue that has been triaged but needs further investigation labels Mar 4, 2021
@meistermeier meistermeier added this to the 6.0.6 (2020.0.6) milestone Mar 4, 2021
meistermeier added a commit that referenced this issue Mar 4, 2021
Respect class hierachy when querying for and mapping to generic classes.
This commit closes GH-2138.
@meistermeier
Copy link
Collaborator

Since our internal tests went also fine for this, it is now available as 6.0.6-SNAPSHOT and will be part of the next patch round. Again, thanks for reporting this and all your feedback.

@myfrontpocket
Copy link

myfrontpocket commented Mar 22, 2021

Just updated to Spring Boot 2.4.4, and this is still broken. I am not getting the correct concrete implementation back, and have failing tests.

This issue outlines mostly what my domain model looks like. #2176

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug A general bug
Projects
None yet
Development

No branches or pull requests

5 participants