Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

@DynamicLabel causing objects to be instantiated as incorrect child type #3036

Closed
Assignees
@keenan-joyce-lg

Description

When using the @DynamicLabels annotation, objects are getting instantiated as the incorrect type if there are values added to the dynamic labels set. This issue has been tested and confirmed on as late as SDN version 7.5.2. This issue also seems similar to this ticket from last year:
#2886.

Here is an example that demonstrates the issue:

Entities

@Getter
@Setter
@NoArgsConstructor
@Node(primaryLabel = "Vehicle")
public class Vehicle {
 @Id
 public String id;
 @Property(name = "name")
 public String name;
 @JsonIgnore
 @DynamicLabels
 public Set<String> labels = Set.of();
}

@Getter
@Setter
@NoArgsConstructor
@Node(primaryLabel = "Car")
public class Car extends Vehicle {
}
@Getter
@Setter
@NoArgsConstructor
@Node(primaryLabel = "Sedan")
public class Sedan extends Car {
}

Repository

@Repository
public interface VehicleRepository extends Neo4jRepository<Vehicle, String> {
 @Query("MATCH (vehicle:Vehicle) RETURN vehicle")
 List<Vehicle> findAllVehicles();
}

Test

@DataNeo4jTest
class VehicleRepositoryTest (
 @Autowired val vehicleRepository: VehicleRepository,
) {
 @Test
 fun `dynamic labels cause incorrect sub-types`() {
 val vehicleWithDynamicLabel = Vehicle().apply {
 name = "Vehicle with dynamic label"
 labels = setOf("Random Label")
 }
 val vehicleWithTwoDynamicLabels = Vehicle().apply {
 name = "Vehicle with dynamic label"
 labels = setOf("Random Label", "Random Label 2")
 }
 val vehicleWithoutDynamicLabel = Vehicle().apply {
 name = "Vehicle without dynamic label"
 }
 vehicleRepository.saveAll(listOf(vehicleWithDynamicLabel, vehicleWithoutDynamicLabel, vehicleWithTwoDynamicLabels))
 val vehicles = vehicleRepository.findAllVehicles();
 assertThat(vehicles.filterIsInstance<Sedan>()).isEmpty()
 assertThat(vehicles.filterIsInstance<Car>()).isEmpty()
 }
}

The above test fails, because vehicleWithDynamicLabel and vehicleWithTwoDynamicLabels get mapped to Car objects when retrieved from the database, when they are nodes of the parent type Vehicle. vehicleWithoutDynamicLabel is correctly mapped to a Vehicle object because it does not have dynamic labels. With one or two dynamic labels, both Vehicle nodes still mapped to Car objects, neither were instantiated as the grandchild type Sedan.

We can see in the following picture, that two of the three Vehicle nodes get mapped to Car because they have dynamic labels:
Image

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      AltStyle によって変換されたページ (->オリジナル) /