No, you do not need 2 separate POJOs. However, you do need 2 separate Repository interface definitions, 1 for JPA and a 2nd for GemFire. I have an example of such an implementation here, in the repository-example
.
In the contacts-core
module, I have an example.app.model.Contact
class that is annotated with both JPA's @Entity
annotation as well as SDG's @Region
annotation in addition to other annotations (e.g. Jackson).
I then create 2 Repository interfaces in the repository-example
module, 1 for JPA, which extends o.s.d.jpa.repository.JpaRepository
, and another for GemFire, which extends o.s.d.gemfire.repository.GemfireRepository
. Notice too that these Repositories are separated by package (i.e. example.app.repo.jpa
vs. example.app.repo.gemfire
) in my example.
Keep in mind, Spring Data enforces a strict policy mode which prevents ambiguity if the application Repository definition (e.g. ContactRepository
) is generic, meaning that the interface extends 1 of the common Spring Data interfaces: o.s.d.repository.Repository
, o.s.d.repository.CrudRepository
or perhaps o.s.d.repository.PagingAndSortingRepository
, and the interface resides in the same package as the "scan" for both JPA and GemFire. This is the same for any Spring Data module that supports the Repository abstraction, including, but not limited to, MongoDB and Redis.
You must be very explicit in your declarations and intent. While it is generally not a requirement to extend store-specific Repository interface definitions (e.g. o.s.d.gemfire.repository.GemfireRepository), and rather extend a common interface (e.g. o.s.d.repository.CrudRepository
), it is definitely advisable to put your different, per store Repository definitions in a separate package and configure the scan accordingly. This is good practice to limit the scan in the first place.
Some users are tempted to want a single, "reusable" Repository interface definition per application domain model type (e.g. Contact
) for all the stores they persist the POJO to. For example, a single ContactRepository
for both JPA and GemFire. This is ill-advised.
This stems from the fact that while most stores support basic CRUD and simple queries (e.g. findById(..)
), though not all (so be careful), not all stores are equal in their query capabilities (e.g. JOINS) or function (e.g. Paging). For example, SDG does not, as of yet, support Paging.
So the point is, use 1 domain model type, but define a Repository per store clearly separated by package. Then you can configure the Spring Data Repository infrastructure accordingly. For instance, for JPA I have a configuration which points to the JPA-based ContactRepository
using the ContactRepository
class (which is type-safe and better than specifying the package by name using the basePackages
attribute). Then, I do the same for the GemFire-based ContactRepository
here.
By following this recipe, then all is well and then you can inject the appropriate Repository (by type) into the service class that requires it. If you have a service class that requires both Repositories, then you must inject them appropriately, for example.
Hope this helps!