I have two databases: Oracle and PostgreSQL where I have multiple schemas - one per each customer. I need to have an opportunity to route datasources by web request. I tried to use Spring's AbstractRoutingDatasource but it works only with single dialect. Are there any other solutions for this task?
I found a solution. You can explicity tell Hibernate which dialect to choose using hibernate.dialect property. So you can implement your own dialect extends org.hibernate.dialect.Dialect class, override all public methods and delegate calls to specific dialects. The good thing is Hibernate calls this (Dialect's) methods before performing any database requests. In my specific case I've implemented a custom dialect with map of dialects I need for my project and now I can use the same repositories and freely choose Postgresql, Oracle or MySQL depending on logged in user
Related
I am trying to understand various dependencies of spring boot.
I have come across three of them:
spring-boot-starter-data-rest
spring-boot-starter-data-jpa
spring-boot-starter-data-jdbc
I would like to know the difference between the three. Tried searching online documents, which say the three are almost related to spring data. how to resolve the confusion?
To add in here I have also found an another dependency
spring-boot-starter-web-services. I think it supports both SOAP and REST. Its just my assumption, I waiting for an explanation
spring-boot-starter-data-jpa is used to access your database with JPA (Java Persistence API)
spring-boot-starter-data-jdbc is used to access your data with jdbc (Java Database Connectivity)
the difference between JPA and JDBC is the level of abstraction. JDBC is more low level, JPA is more 'magic'
and spring-boot-starter-data-rest is used to provide Rest Endpoints on top of your Spring Data repositories.
To do this, you just annotate your spring data repository with a RepositoryRestResource annotation and direct Spring MVC creates the Restful endpoints.
#RepositoryRestResource(collectionResourceRel = "people", path = "people")
public interface PersonRepository extends PagingAndSortingRepository<Person, Long> {
List<Person> findByLastName(#Param("name") String name);
}
This is very handy if you do very CRUD like (Create, Read, Update, Delete) applications.
JPA means "Java Persistence API". It's for querying or saving data in relational databases using object-relational mapping.
REST means "REpresentational State Transfer". It's a style for creating web services that leverages HTTP verbs, a simpler alternative to SOAP.
JDBC starter uses the Spring JdbcTemplate to query or save data in relational databases without relying on object-relational mapping. You write SQL and ask the JdbcTemplate class to execute it in the database using JDBC.
I would say JPA and JDBC starters should be mutually exclusive: either one or the other.
You use REST only if you're writing web services. These may or may not query or persist data in a relational database. I would expect to see both the REST starter and a persistence starter in a pom if a REST service needed persistent data.
Three very different starters.
You ask why Spring Boot has a REST data starter parent that combines the two. In a word: convenience.
Specification
Each tenant has their own database which handles users in greater detail, and there needs to exist a central database which handles:
Tokens (OAuth2)
Users (limited level of detail)
Mapping users to their database
Problem
I've found solutions for multi-tenancy which allows me to determine the datasource depending on the user. However, I'm not sure how I can also link certain crud repositories to this central datasource, and others to variable datasources.
Another solution involved updating the properties file, and using a configuration server (i.e. via git) to trigger #RefreshScope annotated configs. Though I'm not sure if this can work for Datasources, or if this could cause problems later on.
Extra Context
I'm using Spring Boot and Hibernate heavily in this project.
This blog gives a very good tutorial on how to do it.
After a lot of research it looks like hibernate just isn't built for doing that, but by manually writing the schema myself I can inject that into new tenant databases using native queries.
I also had a problem with MS Server DBs, as they don't allow simply appending ;createDatabaseIfNotExist to the JDBC URL, which meant even more native queries (Moving the project over to use MySQL anyway, so this is no longer a problem.)
The application has 2 separate databases, say:
DB1
DB2
and database of different companies are split across these 2 databases, like:
DB1
Company 1
Company 2
Company 3
Company 4
DB2
Company 5
Company 6
Company 7
Company 8
How can such a scenario be configured in hibernate?
All the examples refer either to Schema based multitenancy or Database multitenancy.
Is there any way to configure such a scenario?
To do that you should create two sessionFactory Bean in your config file. and in your DAO layer you call it using qualifier annotation.
You're going to have to create your own implementation of MultiTenantConnectionProvider that handles both database and schema level multitenancy. That should be the path of least resistance.
Here's some slightly outdated info about fighting with spring, hibernate and custom multitenancy: Setting up a MultiTenantConnectionProvider using Hibernate 4.2 and Spring 3.1.1
I will get strategy with separate database and in ConnectionProvider override method getConnection() to set schema.
I this case I can change databases and select specyfic schema for tenant.
Is it possible to use Hibernate with Annotations, without Spring framework for a command line application.
Right now i have spring with hibernate configured for command line application.I have main function which received data and it calls other (namely 'storeDB') object to get AbstractApplicationContext context and save the data.
Like to bring up the hibernate first ( bring up hibernate framework,
connecting to DB) and like to wait for a socket to process the data.
Can it be configured through java configuration than XML
configuration
and is it possible do in Hibernate(with annotation) without Spring?
Yes of course you can:
Use Hibernate annotations (without XML configuration) to setup your database connections and map
your entities to your database, for further information about it take a look at:
Hibernate with Annotation.
TutorialsPoint Hibernate - Annotations tutorial.
Use only Hibernate without Spring in a Java Application to manage your persistence strategies, because they are two independents frameworks:
You can see from the Hibernate Definition that:
Hibernate ORM enables developers to more easily write applications whose data outlives the application process. As an Object/Relational Mapping (ORM) framework, Hibernate is concerned with data persistence as it applies to relational databases (via JDBC).
And from the Spring project definition that:
The Spring Framework provides a comprehensive programming and configuration model for modern Java-based enterprise applications - on any kind of deployment platform. A key element of Spring is infrastructural support at the application level: Spring focuses on the "plumbing" of enterprise applications so that teams can focus on application-level business logic, without unnecessary ties to specific deployment environments.
Conclusion:
As you can see Hibernate and Spring are two differents frameworks that handles differents levels of Java Applications.
I have a requirement where i need to configure a Spring based application to work with two databases. We have two databases, one that we use to keep the live data and the other database is used as a datawarehouse and contains archived data (which has the exact structure as the Live db).
To keep it simple, assume that there is a request to search for a product. What the application should do is to search for the product details in the Live database and if not found it will check the archive database.
If i need to configure such a setup, do i still need to configure to datasources and would the search code have to use the first datasource to check the live database and if not found it will run another query using the archive database?
The above is probably doable but i am wondering whether there is a better way of doing this. For example, is it possible for the application to work on a single datasource even though behind the scenes it actually works with two databases?
The application is based on Spring, JPA/Hibernate, SOAP and Mysql database and Jboss 7 as the application server.
Any examples showing how this is configured using Spring and Jboss would be very useful.
Thanks
Spring has exactly what you want - the AbstractRoutingDataSource. See this blog post on how to use it. In your case, you need to switch the datasource during one request, so you'll need to have 2 transactions, switching the datasource between them by changing the datasource indicator on the ThreadLocal:
For these DAOs, demarcate the wrapping Service-layer either with distinct packages, class names, or method names
Indicate to Spring that the Service-layer method calls should run in their own transactional contexts by annotating with #Transactional(propogation=Propogation.REQUIRES_NEW)
Create an Aspect (using AspectJ annotation #Aspect) to fire around the service-layer method calls (using #Around) to set the ThreadLocal value before the method call, and to unset it afterwards
In the #Controller, simply call the Service-layer methods. The Aspect will take care of setting the values to indicate which datasource to use, and the AbstractRoutingDataSource will use that datasource in the context of each transaction.