spring-projects / spring-data-rest

Simplifies building hypermedia-driven REST web services on top of Spring Data repositories
https://spring.io/projects/spring-data-rest
Apache License 2.0
913 stars 559 forks source link

Spring Data Rest shouldnt rely on underlying data store api for entity references [DATAREST-326] #707

Closed spring-projects-issues closed 10 years ago

spring-projects-issues commented 10 years ago

Aaron Loes opened DATAREST-326 and commented

we implemented our persistence with mongo initially and are in the mode of switching to couchbase. Doing so, we're finding that referencing is highly relying on DBRef from mongo to perform relationships. This should be abstracted away and implemented outside of the underlying implementation. Same goes for searching, indexing, and the like


Referenced from: commits https://github.com/spring-projects/spring-data-rest/commit/bba78849bda96c9484149f911f740863dd58d624, https://github.com/spring-projects/spring-data-rest/commit/2d64fb4d840d956998c0a6e40c69e28267328a63

spring-projects-issues commented 10 years ago

Oliver Drotbohm commented

Any chance you elaborate on that a bit? In fact, SD REST doesn't know anything about the store details at all. It's working with the persistence metadata exposed by the MappingContext. That's what makes it possible for us to support different stores without store specific adapters in the first place.

What do you mean with "perform relationships"? What does "Same goes for searching, indexing, and the like" mean? We expose search resources for the repository query methods you expose. We don't deal with indexing at all

spring-projects-issues commented 10 years ago

Aaron Loes commented

Thank you for the quick reply. My apologies for the vague bug request and i probably should have marked it as a feature request (was in a hurry).

The problem we are having is that we are writing an application that can run on either mongo or on couchbase. Currently to get relationships working for mongo, we need to annotate our models with @DBRef and there is no counterpart for this in couchbase (would have same issue if using JPA over SQL), but for now assume there is. This puts a dependecy on mongo and couchbase for our domain models. It would be ideal if there was some inversion of control here where just annotating with @Reference will inform the underlying implementation (either spring-data-mongo, spring-data-couchbase, etc) to use a @DBRef (or some sort of proxy object for lazy fetching) if mongo and whatever the couchbase equivalent would be. The idea also follows for implementing indexes and search queries and other commonalities neede for all spring-data-x projects

spring-projects-issues commented 10 years ago

Oliver Drotbohm commented

Thanks for the comment, Aaron. This (requiring store-specific annotations) is actually a fundamental design decision we made with Spring Data for a couple of reasons:

  1. Data-store exchangeability is a myth. NoSQL data stores have their strengths when persisting certain kinds of data: MongoDB is great for aggregates, Neo4j is awesome at persisting highly interconnected data. That in turn means, that the data structures you model will have to vary depending on the store you persist them into. With MongoDB you want to avoid references, in Neo4j they actually become a first class citizen of the model.

As we do not want to create the impression that exchangeability is cheap, these all-abstracting annotations do not exist. In short, this is explicitly a non goal, as we want users to use the stores the way the stores are used best. NoSQL is not about "data structures into whichever store" but "the right store for the data structure at hand".

  1. The devil is in the details. Actually there had been a Spring Data Document project in the first place, which was supposed to create a common abstraction for all document databases (MongoDB, CouchDB etc.). It quickly turned out that, if you want to use store specific features (indexing) you need to get access to the specific store's knobs to make that work. Both Couchbase and MongoDB are document stores, yet they're completely different beasts in the way they work, in the abstractions and concepts one has to understand (MongoDB aggregation VS. Couchbase views VS. etc.). Trying to abstract from these is an explicit non-goal, because it's only important if exchangeability is a concern, which it isn't as explained in 1.

The core goal of Spring Data is a consistent programming model (annotation based mappings, templates, repository abstraction) while retaining store-specific traits and features. Everything else is a consequence of that core missions statement.

If we focus on references in particular, Spring Data actually has an @Reference which indeed is evaluated by the metadata and @DBRef actually carries it. So given the assumption Spring Data Couchbase correctly handles that as well you should be able to use it across stores. With the paragraphs above, however, I wanted to prevent the impression that is kind of stuff is something we're going to extend and try to derive store specific information from it.

Generally speaking if you have an app to run against both stores, you need to live with both mapping annotations. Annotations have the benefit of the JVM not barking at you if they're not on the classpath. We have a customer with an app on both JPA and MongoDB that improves this situation by using AspectJ to add the mapping annotations to the types when the build is run. So they have dedicated build profiles for JPA and MongoDB

spring-projects-issues commented 10 years ago

Oliver Drotbohm commented

Closing this as even if we consider this an issue, it's not one that's going to be solved in Spring Data REST