Hibernate Multitenancy with different tables per tenant - java

Is there a way to define with hibernate which entities should be created in which tenant? Because for different tenant, tables are not the same.
And second question, is it possible to configure (also with hibernate) that I want to get access to tenant2 tables from tenant1.
I use embedded h2 database. I would like to automatically create tables with hibernate.hbm2ddl.auto and fill these tables with flyway migration files.

Well, I'm using a Multitenant Architecture in Spring and I can help you with what I'm doing.
1: If you have different tables for different tenants you could either use a TenantFilter over your Entity or you can define your customized schema in schema.sql and use JdbcTemplate to execute the SQL.
I would prefer the second option over the first because it guarantees the correct schema creation.
2: You can make a switch to your tenant2 from tenant1 using a TenantContext and once you're done with your processing you can switch back to tenant1.
There are many demo projects on multitenancy with spring boot on GitHub you can have a look there.

Related

In Java, Spring maintaining database without any scripts

I am working on a project in Java (using Spring Boot, Thymeleaf, Hibernate, JPA, MySql). Every time I create a new Model Class, I have to create a table in the database or if I make any change in the Model class I have to alter the table by myself. Is there any way to avoid this database related stuff. For example I will make Model classes and declare their relationships my Database tables will be generated automatically. In future if I make any changes to my classes they will be applied to the database automatically without loosing any data.
Previously I worked on PHP, Laravel. There all I needed to do is 1) run command php artisan make:migration create_posts_table, 2) declare columns like $table->string('title');, $table->foreign('user_id')->references('id')->on('users'); and then 3) run command php artisan migrate. That's it. No SQL scripts needed. I was wondering if Java, Spring has something like this.
Sure you can do it.
Use spring.jpa.hibernate.ddl-auto=update in your application.properties.
You can also use more advanced tools like https://www.liquibase.org/
Ideal way
spring.jpa.hibernate.ddl-auto=none
In my opinion, the ideal way is to create one SQL file which will create the schema at the startup for us.
To let Spring Boot to create it for you
spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.ddl-auto= # DDL mode. This is actually a shortcut for the "hibernate.hbm2ddl.auto" property. Defaults to "create-drop" when using an embedded database and no schema manager was detected. Otherwise, defaults to "none".
Other Possible values: create, create-drop, validate
More Detailed Explanation
You can do migration using Flyway, it's similar to Laravel migration.
Add the dependency and put your migration SQL files to classpath:db/migration. Flyway will automatically check the sql files version and apply any pending migrations.
https://flywaydb.org/documentation/plugins/springboot

Hibernate HT_ Temporary Tables ON JOINED inheritance, Migration from Hibernate 3.4.0.GA To 5.1

I'm trying to migrate an application from Hibernate 3.4.0.GA to Hibernate 5.1, and after complete the required changes on java code, when I deploy the application I'm watching how Hibernate is trying to create HT_ tables (global temporary), one for each #Inheritance annotated entity.
Searching on Google I've found why the tables are being created.
But in my case we are not allow to change de database to add new tables.
My Inheritance model only has one level of Inheritance and its simple, example
Does anyone knows any alternative representation for a hierarchical table structure that I can use to avoid the HT_ tables creation, or some Hibernate configuration to archive the same purpose?.
I can change the inheritance hierarchy on our entities or the Hibernate configuration. I can also asume an exception on deploy caused by the non creation of the tables if it´s non blocking for the rest of the deploy.
Thank you in advance.
UPDATE 1: New info from Hibernate official forum.
UPDATE 2: The Bug was fixed
UPDATE 3: A blog entry explaining different bulk Strategies related to the issue
As in update one on this link is more info from Hibernate official forum with a possible solution.
UPDATE: Link with the solution
If you use Oracle Database with Spring and not sure where to define property for hibernate can do the following.
Add
spring.jpa.properties.hibernate.hql.bulk_id_strategy: org.hibernate.hql.spi.id.inline.InlineIdsInClauseBulkIdStrategy
In application.yml file from resource folder.

How to switch between db in hibernate?

I have two databases defined in my web application. One for fashion and one for sports. Currently Im accessing the sports database. Now that I want to change it to fashion database means how can I do that ? I'm using spring with hibernate. Is there any in-built support for this either in spring or hibernate ?
EDIT 1:
I will have a web page where I can choose which database to use and then the changes should get reflected automatically. Is there any way to do it ?
FYI : Both the databases will have the same design. Only the data will be different
Hibernate specific configuration may differ slightly, but with JPA you need to have two EntityManagerFactories configured, one for each database. Then you would use either one depending on which database you want to access.
You can't do this with a single EntityManagerFactory (or the pure Hibernate equivalent).
I think this is an answer to your question. You can simply add a second PersistenceUnit and create a second Factory for your Entity Managers for it.
I hope this helps!
Kind regards
Mysql only has one database. It has many schemas (which it calls databases). You can query a table in another schema by prefixing it: schema_name.table_name .

Distributed query with Hibernate multi-tenancy

I am using Hibernate's multi-tenancy feature via JPA, with a database per tenant strategy. One of my requirements is to be able to run a query against a table that exists in each database but obviously with different data. Is this possible?
Thanks in advance for your time.
Nope. this is not possible because when hibernate runs queries it is already initialized with a connection. MT support in Hibernate is basically done a little "outside of Hibernate" itself. It's kind of feeding hibernate with a proper connection and when it's fed :) it's bound to that connection.
If you need cross-tenant queries you might want to reconsider multitenancy or change JPA provider to the one that support "shared schema approach" e.g. EclipseLink. With shared shema approach you have two choices:
run native query agains table containing mt-aware entities
create additional entity - dont mark it as multitenant - map it to the table containing mt-ware entities and run JPQL query in standard manner

AbstractRoutingDataSource + JPA won't create table except defaultTargetDataSource

I use JPA annotations (Hibernate implementation) to initialize my DB schema. And i follow the article DYNAMIC DATASOURCE ROUTING to implement the dynamic datasource routing class.
However, i have two databases (mapped 2 data sources). I set the first data source as defaultTargetDataSource. then start my application. When my application try to access 2nd data source, it tell me the table doesn't exist. It seems AbstractRoutingDataSource only create the table for the default data source but other data sources.
Is there any idea to create schema in all databases ?
PS.I'm using AbstractRoutingDataSource to implement my own DB shards.
I guess that you are using the hibenate configuration:
spring:
jpa:
hibernate:
ddl-auto: update
to reflect the entity changes to the database schema. This works fine as long as we use a single data source that is configured to be connected at startup.
However, if you have multiple data sources it is not possible to use this feature. The general approach with AbstractRoutingDataSource is to not have a data source at startup but select it at runtime.
If you select a primary data source, then it will be only applied to the primary one as hibernates applies this feature at startup, but the remaining databases will not be migrated.
To reflect the changes to all of your databases you can use a database migration tool such as Flyway or Liquibase.
Flyway is using SQL and pretty easy to configure and use to use.

Categories

Resources