Reputation: 38777
Taking an example: I want some entities to be persisted in MongoDB and some in Cassandra.
I have my repository interfaces extending CrudRepository
. My Cassandra entities have @Table
and my MongoDb entities have @Document
annotations.
However, on startup, spring-data attempts to create an instance of a MyMongoObjectRepository
, and thus complains that "Cassandra entities must have the @Table, @Persistent or @PrimaryKeyClass Annotation".
How are the libraries discovering which repository interfaces they are supposed to implement, and how can I control them so they don't try to implement them for unsupported entities?
Further question: if I wanted to store some entities in both storage systems, can multiple implementations of a single repository be generated, or do I need an interface for each store?
Edit
On further inspection, the problem seems to be from the entity scanning rather than the repository scanning. Both mappers pick up all the entities (as their annotations all extend @Persistent
). One of the Mongo entities has a nested entity (without any annotations) that the Cassandra mapper cannot deal with.
Upvotes: 1
Views: 1038
Reputation: 38777
Problem is that all the different entity scanners use @Persistent
as an annotation they're looking for, while all the repo-specific annotations (@Table
, @Document
, etc.) also have @Persistent
as a meta-annotation.
Therefore, the entities for the different repositories must be in separate packages, and you must construct your own scanner in order to pass the packages to it, as it doesn't not accept a generic filter.
Upvotes: 0
Reputation: 21
You can use a basePackages
setting in @EnableMongoRepositories and @EnableJpaRepositories to specify where they should look for repository definitions.
Like so:
@EnableMongoRepositories(basePackages={
"com.some.package.to.look.inside",
"com.some.package.to.look.also.at"
})
And
@EnableJpaRepositories(basePackages={
"com.some.differentpackage.to.look.inside",
"com.some.differentpackage.to.look.also.at"
})
For this to work you need to namespace your repository definitions in sensible packages.
Answer to your follow up question:
If you wanted to store entities multiple places at once I would implement a service in front of the repositories making use of @Autowire to dependency inject the repositories and setting a @Transactional on the service method which calls repository methods. Having @Transactional on the service method ensures that if an error would occur while saving it will ensure that no half-way saves are left laying around, even doing rollbacks if necessary.
Edit:
@Transactional does not work for db's that do not support transactions like Cassandra and MongoDB.
Upvotes: 2