Is there any possible solution to dynamically create a datasource at runtime? I have come across AbstractRoutingDataSource e.g. here a few times however in my case I would not know the database name at the time of config beans starting up as we will be creating databases during client on-boarding and would prefer not to have to bounce the app, so I would want to select the correct datasource based on some client id in the request header, and add the new datasource to the spring context on the first request for this client.
Yes, like any other bean you can add DataSource bean in runtime.
There are several ways to do this: https://medium.com/#venkivenki4b6/spring-dynamically-register-beans-in-4-ways-at-run-time-c1dc45dcbeb9
Related
I'm currently working on implementing schema-based multi-tenancy for my Spring Boot / JdbcTemplate API application. I figured out that for it to work, in the DAO layer, I need to dynamically change the schema of the DataSource used by JDBCTemplate during the runtime, in other word create a new one, but I can't find any information on how to set properly the schema for the DataSource I'm creating.
EDIT
Here are some details that might be important : the schema is defined in the url of the API endpoints I created, as a mandatory variable: if the user calls the URL localhost:9090/schema/MyNewSchema/Test, the schema variable is MyNewSchema and I have to create a DataSource with the proper pointed schema MyNewSchema.
Found a possible answer if someone faces the same issue : https://springboot-vuejs-reactjs.blogspot.com/2019/08/springboot-multi-tenancy-with.html
I decided to use an AbstractDataSource class, as mentioned in the article, and to override the public DataSource dataSource() bean in the #SpringBootApplication class, with an injection of the AbstractDataSource class created earlier. This allows me to manipulate the DataSource used by JDBCTemplate dynamically during the application runtime.
Furthermore, in my AbstractDataSource class, the DataSource objects I manipulate are HikariDataSource, allowing me to define the schema I want the DataSource to point with a hikariDs.setConnectionInitSql("ALTER SESSION SET CURRENT_SCHEMA = MY_SCHEMA") statement (cf Configure OracleDataSource programmatically in Spring Boot with a default schema). In my case, I'm using Postgresql, so the SQL statement is SET SEARCH_PATH TO <schema-name>
It works pretty well !
I was working on a Spring-data-jpa project with spring boot, I see that the creation of repository beans required a datasoure bean to be present, Why is it so?
And can a repository bean be created without datasource bean.
The purpose of a repository is to load and save data into a persistent store.
Spring Data JPA does that using JPA so it needs an EntityManager which in turn need a DataSource.
Strictly speaking the DataSource is only used once the database is actually accessed.
While you definitely nee a DataSource bean you may delay the construction of a normal DataSource by providing a wrapper which instantiates the the actual DataSource at a later point in time.
DelegatingDataSource might be of help, either as a basis class or, since you are going to change the DataSource as a template for an implementation.
See the somewhat related question https://stackoverflow.com/a/61208585/66686
I went through the Data Access With Spring tutorial and the in memory database they use in step 3 is working. But, I'm not clear on what I need to add/change to get it to query my development (Oracle) database now?
I want to use Hibernate, do I still need this JPAConfiguration class or would I have something Hibernate specific?
Please don't just post a link to the Hibernate reference. I'm reviewing that as well, but since I'm also using Spring, it's not clear to me the proper way to load the hibernate.cfg.xml and inject the Hibernate session in that context.
Don't be blocked by the fact that the class is called JPAConfiguration. You need to understand what the class does. Note that it has the annotation #Configuration which you can use along with AnnotationConfigApplicationContext to produce a Spring bean context.
That functionality is described in the Spring documentation for The IoC container.
What you need to change is how your DataSource and EntityManagerFactory beans are created. You'll need to use a DataSource that gets Connection instances from a JDBC Driver that supports Oracle databases.
I'm a Spring novice user.
I have a database table which is static in nature and contains only a few records.I want a Map-like structure(id - name) that holds two columns of this table. This Map must be loaded/initialized when the web application is started and must be applicable throughout the application's context, independent of the users sessions and must be read-only. This way, I can save a lot of DB queries as the different operations will simply read from this Map.
While I'm aware of ServletContextListener etc. of Java EE, I don't know how to achieve the same in Spring. Is a Spring Service bean the right place/way to initialize and store such a Map?
Please guide me about the same.
You can create a regular spring bean exposing a method which loads the data you require from the database and stores it in your map. Annotate this method with #PostConstruct and spring will ensure that it is called when your application context starts, hence loading your map.
You could use springs JdbcTemplate to load your data within this method
See Spring PostConstruct doco for information on the #PostConstruct annotation
See JdbcTemplate doco for information on JdbcTemplate
You can configure lists, sets and maps in a Spring XML configuration. See here for more examples.
I have a method that I've annotated with the #Transactional annotation.
The problem is, the datasource that the code runs against can change! Briefly, is it possible to change the transaction's datasource while the application is running?
In depth:
The application lets users select a database to run sql against. They can change the database at runtime. I'd like the application to run all the sql in a transaction - the sql groups are always against the same datasource, so that's not an issue.
The issue is, I don't know how to changem the transaction to use a different datasource. Varying articles have suggested the JTATransactionManager, but we're on tomcat, so no dice.
Is there a simple way to do this, or will we need to ditch the #Transactional annotation and do something else?
And if so, what is that "something else?"
Oh, the database is db2, if that's any use!
thanks!
One of the possible solution
Configure all the possible datasources in spring config
a. Datasource1 for DB1
b. Datasource2 for DB2 etc..
Maintain a map of above datasource in a service class and create spring's JDBCTemplate out of selected datasource based on some key from map.