spring-projects / spring-data-neo4j

Provide support to increase developer productivity in Java when using Neo4j. Uses familiar Spring concepts such as a template classes for core API usage and lightweight repository style data access.
http://spring.io/projects/spring-data-neo4j
Apache License 2.0
828 stars 620 forks source link

SDN 6.2.1 - Can't use template.saveAs(entity, ClassBasedProjectionDTO.class) #2486

Closed mrksph closed 2 years ago

mrksph commented 2 years ago

Hi

I'm using Spring Boot 2.6.3 with SDN 6.2.1

In the following link: https://community.neo4j.com/t/saving-node-without-updating-node-in-relationship/4201/4

@meistermeier Gerrit says that from 6.1 onwards, we can use Projection-based persistence. This was really good news for me because it solves a problem we've been facing for a long time: Updating properties on nodes with many (500+) relationships.

Previously, when dealing with this use-case, we had to move from our first approach which was going repository-based persistence first to CustomRepositories with manual query building.

It's a tedious task because as we came up with this problem AFTER developing many of the services we have refactoring is needed.

@Node
class Thing {
 String code;
 String name;
 String country;

 @Relationship
 List<Thing> related;
}
interface ThingOpenProjection {
 String getCode();
 String getName();
}

So, I found that new functionality from SDN and I'm testing it. So far, using interfaces works:

Thing thing = repository.findThingByCode("code");
thing.setName("New Name");
template.saveAs(thing, ThingOpenProjection.class);

But using class-based projections won't work... When I try to save as follows:

@Getter
@Setter
class ThingDTOProjection {
 String code;
 String name;
}
Thing thing = repository.findThingByCode("code");
thing.setName("New Name");
template.saveAs(thing, ThingDTOProjection.class);

I get an Exception:

java.lang.IllegalArgumentException: Projection type must be an interface!

Is there any plan on adding this functionality? It'd great to be able to save it like that because it'd allow us to map the DTO projection to a POJO easily with ModelMapper or any other mapping library.

Interface-based projection persistence won't allow us to map from an interface to an object.

Thank you.

mrksph commented 2 years ago

Closing this issue.

ModelMapper allows interfaces when using .map(source, destinationTypeClass)

Edit to clarify: saveAs passing an Interface projection returns a Proxy object so not really a problem.