Spring Data JPA | handle multiple DB without entityManager, DataSource and TransactionManager - spring-data

I've read several examples ex1, ex2, ex3 for using several database on Spring Data (JPA), all of them suggest creating one Configuration file for each database, and three bean (EntityManager, DataSource and TransactionManager) for each entity. Is it the only way we can handle multiple database or there is easier way to do this ?

Related

Change spring data r2dbc context to use R2dbcRepositories in a different database

How can I change spring data r2dbc repositories target-datatabase (maybe I am talking about 'Context')?
Let me explain better.
I am managing(ConnectionFactory Properties) 'connection factory' to execute SQL-DDL scripts in any database I want - OK; however, R2dbcRepositories (REactiveCruRepository) methods, are not follow this database I have configured ConnectionFactory Properties.
How Can I change ConnectionFactory Properties, in order to, REactiveCruRepository points for this configuration done (meaning a new database)?
It is very easy to configure another connection factory for your R2dbc Repositories.
Check my example about multiple R2dbc connection factories.

How to keep a history of edit of Entities in a JPA application

A JavaEE and JPA application need to keep a record of all the changes made by the user.
Currently, for all the entities, there are fields to record createdBy and lastEditedBy properties. Yet, the requirement of recording all edits is not possible with those properties.
What is the best way to record the history of all edits for a particular entity?
I do not use Spring.
You can use Javers which is db and framework agnostic tool for maintaining operation history.
There are two big differences between JaVers and Envers:
Envers is the Hibernate plugin. It has good integration with Hibernate
but you can use it only with traditional SQL databases. If you chose
NoSQL database or SQL but with another persistence framework (for
example JOOQ) — Envers is not an option.
On the contrary, JaVers can be used with any kind of database and any
kind of persistence framework. For now, JaVers comes with repository
implementations for MongoDB and popular SQL databases. Other databases
(like Cassandra, Elastic) might be added in the future.
Envers’ audit model is table-oriented. You can think about Envers as
the tool for versioning database records.
JaVers’ audit model is object-oriented. It’s all about objects’
Snapshots. JaVers saves them to the single table (or the collection in
Mongo) as JSON documents with unified structure.
You can also achieve this using triggers and storing object differences.
Edit:
JaversAuditableAspect for any kind of repository.
It defines the pointcut on any method annotated with the method-level #JaversAuditable annotation. Choose it if you have repositories that are not managed by Spring Data.
#Bean public JaversAuditableAspect javersAuditableAspect() { return new JaversAuditableAspect(javers(), authorProvider(), commitPropertiesProvider()); }
You can use Hibernate's Envers to audit your entities. It allow you to keep track of ALL changes made to entities - even deleted ones. Most probably you are already using Hibernates (as JPA provider) so integration should be a no problem.
https://hibernate.org/orm/envers/

Creating Datasource Dynamically in SpringBoot OpenJPA Application (Implementing Multitenancy with OpenJPA)

I am creating a Springboot application with OpenJPA.
My requirement is that I need to connect to multiple datasources dynamically and the datasource credentials are obtained at runtime by calling some rest-endpoints.
Here is the controller class:
#RestController
public class StationController {
#Autowired
BasicDataSource dataSource;
I have a service which returns me the jdbc_url depending on the customer name:
public String getDSInfo(String customername){
// code to get the datasource info (JDBC URL)
}
My questions are:
Is there a way in which I can create datasources at runtime by getting datasource credentials by calling some other service (which takes the customer id and returns the customer specific datasource) ?
Since my application is a web based application, many customers will be accessing it at the same time, so how to create and handle so many different datasources?
NOTE:
The code will get information about the customer specific data source only by firing some service at the runtime, so I cannot hardcode the datasource credentials in the XML configuration file.
I found some implementations with Hibernate but i am using Springboot with OpenJPA. So need OpenJPA specific help.
It sounds like you want a multi-tenancy solution.
Datasources are easy to create programmatically, just use a DataSourceBuilder with your connection details pulled in from a central source (e.g. a central config database or Spring Config Server).
Then you'll need to look at a multi-tenancy framework to tie the datasources back to clients.
See here:
https://www.youtube.com/watch?v=nBSHiUTHjWA
and here
https://dzone.com/articles/multi-tenancy-using-jpa-spring-and-hibernate-part
The video is a long watch but a good one. Basically you have a map of customer data sources (from memory) that allow an entityManager to pick up a datasource from the map by using a thread scoped custom spring scope of "customer" which is set when a user for a particular customer somehow logs into your app.

spring batch transaction manager clarification

we have two diff datasource (one for spring batch and one for biz domain). When we configure spring batch job, where does transaction manager supposed to reference. Is it datasource pointing to spring batch schema or biz schema?
I would say you should use same transaction manager for your data and meta-data, so that they are consistent.
Standard SB transaction manager is the one pointed by bean named transactionManager.
If you have more than one transaction manager in your spring config, you'll need to specify the name of the bean you want to use.
If you have more than one datasource, one for SB metadata tables and one for processed data, you need distribuited transaction.

Spring Data JPA Repository CRUD Testing

I'm playing around with the Spring Data Repository and have a question on writing CRUD tests. I have written many CRUD tests against Hibernate DAOs and EJB 3 entity beans where I create and entity, flush it to the database, clear the entity manager, and read it back by ID. The entity manager is cleared so the first level cache is not hit on the read.
Using the Spring Data repository I can't find a way to clear the underlying entity manager used by my test so my read is not going back to the actual database, making my test invalid.
Is there any way to clear the entity manager in the test? Is there a way I can inject one into my test so that it is used by the repository?
Thanks!
Cory.
Try it by injecting the entitymanager like this:
#PersistenceContext
EntityManager entityManager
and make your test transactional by setting the #Transactional attribute on your test method. Then inside the method you can call the entityManager.flush() method.
Regards
If you wish the EntityManager to be cleared automatically you can set #Modifying annotation’s clearAutomatically attribute to true.
Please see here