-
Notifications
You must be signed in to change notification settings - Fork 617
Allow interfaces in domain model hierarchies. #2201
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
Comments
I created an example from your description here: https://github.com/meistermeier/neo4j-issues-examples/tree/master/gh-2201 |
I think the issue is this: when you create a data model (a set of entities) and something is not well configured in one of the entities, SDN when trying to resolve and register the model, it makes another call to the same method again and the entity is found already registered and then it throws an exception. The exception may be valid but it is not informative at all and it does not tell you what is the real issue with the data model (could be a field type in the data model that is not supported by SDN, etc... the issue could be anything on the entity, but the error is not helping to figure out what is wrong with the data model. |
I added you to the repo: https://github.com/hamidbm/springboot-rest-datastore |
Hi
This is SDN 5.x and Neo4j-OGM. It is not needed and will cause issues. This is not a driver, this a transport module for OGM.
public class Config extends AbstractNeo4jConfig implements Trace {
@Value("${spring.neo4j.uri}")
private String url;
@Value("${spring.neo4j.authentication.username}")
private String username;
@Value("${spring.neo4j.authentication.password}")
private String password;
@Bean
public Driver driver() {
String neo4jURL = System.getProperty("NEO4J_URL");
if ( neo4jURL == null ) neo4jURL = url;
//info("neo4jURL is: {}", neo4jURL);
return GraphDatabase.driver(neo4jURL, AuthTokens.basic(username, password));
}
@Bean
public Neo4jTemplate neo4jTemplate(Neo4jMappingContext mappingContext) {
return new Neo4jTemplate(neo4jClient(driver()), mappingContext, databaseSelectionProvider());
}
} is unnecessary when using our starter. You are duplicating what is there 100%.
|
Same with the application: Why excluding the auto config and than recreating it? @SpringBootApplication(exclude={Neo4jDataAutoConfiguration.class})
//@EnableNeo4jRepositories("XXX.neo4j.repository")
//@ComponentScan({"XXX.sb"})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public Neo4jDataProperties neo4jDataProperties() { return new Neo4jDataProperties(); }
} |
You can omit all the the See: https://docs.spring.io/spring-data/neo4j/docs/6.0.7/reference/html/#conversions |
I can reproduce the behavior. The underlying issue is that you have public interface PLI {
} and @Node("PLI")
public class PLIEntity implements PLI {
} Both objects triggering the creation of a persistent entity under the label Your statement about repositories was kind of a red herring: It does happen only when you add Anyway, apart from the flaws I mentioned above, I do like your approach and would learn more about you having success in a modularized world. FWIW we are preparing the CypherDSL to be fully modularized soon. |
While technically possible, Spring Data Neo4j prevented a proper use of interfaces in domain hierachies due to the fact that it checks whether a primary label has been used already in a domain model. That check can be triggered at different point in times: Either when initializing the persistence context with a predefined set of entities or when an interface based entity is refered from an implementation of itself. This commit changes the following approaches: * Interfaces won't contribute to the index of entities by primary label * The explicit or implicit names of interfaces implemented by an entity will contribute to the list of additional labels. However, we don't traverse the graph of interfaces to the top * When hydrating instances we must check whether the target is an interface. If so, we go through the list of all known persistent entities and look for one that can be assigned to the interface and which spots all the mapped labels In addition we fixed some bugs when selecting the target entity type when saving relationships. Also, `@Relationship` without a given relationship type name will work now without messing up the type name. This allows for the following scenarios: 1. Creating an API module being free of Spring or Neo4j based annotations. That API module can than be implemented by different Spring Data stores that support interfaces in their hierachies like we do now then. 2. Putting an explicit `@Node` annotation onto an interface so that the implementation can be arbitrary named (Which is probably a rarer use case). 3. Using polymorpmic relationships: If an interface has multiple implementations in the same project, the interface and it's implementations can both be annotated. The annotation on the interface is going to be the primary label and the labels on the annotated implementations are the selectors for picking out the class to hydrate during loading. This closes #2201.
Thank you for input, it was super valuable for us. Fix is in place and so are docs. Please also have a look at the commit message of 43a3047. |
Add another test to verify multi-interface support. Mention in the documentation not to use interfaces with repositories.
Add another test to verify multi-interface support. Mention in the documentation not to use interfaces with repositories.
Thanks Michael and Gerrit for looking into this. And please feel free to update the sample project on GitHub if you want. The point is to be able to create a good modularized template that we can share with the world (and explain in the README file how to create a well modularized app for Neo4j which can have swappable persistence layers...). |
Thanks @hamidbm again for your feedback. I have a working project on the module path: See especially my I will watch your repo. 👍 |
I have few Entity node classes (PurchaseEntity, PLIEntity, EntitlementSetEntity, EntitlementEntity, ...) and the server can only start if not more than one repository interface is defined. Currently I have one repository interface (PurchaseRepository), but when I add another repository (like EntitlementRepository for example for the entity Entitlement), the server cannot start and throws the following error:
Caused by: org.springframework.data.mapping.MappingException: The schema already contains a node description under the primary label PLI
Only the entity PLIEntity is annotated with @node("PLI"), the other entities have their own labels, but somehow SDN is thinking all entities are labeled with PLI label
Entities are like this:
@node("Purchase")
public class PurchaseEntity {...}
@node("PLI")
public class PLIEntity {...}
@node("Entitlement")
public class { ... }
etc...
The text was updated successfully, but these errors were encountered: