-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support multitenancy with multiple persistence units #11772
Conversation
* if not set. | ||
*/ | ||
@ConfigItem | ||
public Optional<String> multitenantSchemaDatasource; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@michael-schnell @Sanne I'm not entirely sure this is useful now that we can define a datasource for a PU. Or in the case of the schema do you want to use another datasource when the tenant is defined?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAICT there is actually zero difference between SCHEMA
and DATABASE
in Hibernate multitenancy, so I don't think you need two things.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know about Hibernate ORM but it makes a difference here as things are handled in the Quarkus extension. I'm unclear though if we really want this.
I agree this needs more discussions and thoughts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There might not be a difference within Hibernatate between SCHEMA and DATABASE, but there is one if you need to generate to database schema with Flyway.
AgroalDataSource dataSource = Arc.container().instance(AgroalDataSource.class).get(); | ||
|
||
if (multiTenancySchemaDataSourceName == null) { | ||
AgroalDataSource dataSource = getDataSource(dataSourceName); | ||
return createFrom(dataSource.getConfiguration()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@michael-schnell @Sanne I'm not sure I understand the need to somehow copy the existing datasource?
configurator.addQualifier().annotation(DotNames.NAMED) | ||
.addValue("value", persistenceUnitDescriptor.getPersistenceUnitName()).done(); | ||
configurator.addQualifier().annotation(PersistenceUnit.class) | ||
.addValue("value", persistenceUnitDescriptor.getPersistenceUnitName()).done(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be "name"
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah OK, I thought it was the javax.persistence annotation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I decided against it as they are quite confusing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And also I needed it to be a qualifier.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense
I can't comment on the Hibernate specific stuff, but the Quarkus specific stuff looks great :) |
Alright, @Sanne, after looking over this stuff, and because coincidentally I happened to be working on multitenancy in HR yesterday, so I was forced to take a close look at how that worked, I gotta say this looks kinda wrong to me. If I understand correctly (I may not!) You've added a second layer of Quarkus-specific tenant resolvers and connection providers on top of the resolvers Hibernate already has I think because you want these to be CDI components, rather than being configured by properties. But the code is really nonsimple and essentially introduces new Quarkus-specific APIs that mirror APIs already in Hibernate. (Again, assuming I understand correctly.) I think this is all just the wrong way to go about it. First of all, I think Hibernate's multitenancy stuff is almost useless in this context. It doesn't actually really do anything except for allowing you to write code to assign connections to tenant ids. It's essentially reasonable in Hibernate where we don't assume any sort of control over the container or non-container environment, but I don't see how it's reasonable here. (Note tangentially that the whole There are significant problems with doing multitenancy at the level of the Hibernate extension, including that any non-Hibernate code doesn't automatically run in the context of the current tenant. What I think should happen here is that multitenancy should be an aspect of the Quarkus datasource, and it should bypass Hibernate multitenancy entirely. If we do want to support Hibernate's builtin multitenancy APIs, we should do that in a way that is compatible with existing code that users have, and just let them configure it by properties as they usually would in Hibernate. |
FWIW, I have absolutely no opinion about how things were done as I was not involved in the initial multitenancy patch. I just made the existing code work with multiple persistence units. If we want to rewrite this, it's something for 1.9 and is orthogonal to this PR. |
Yes @gsmet I know that, I just don't have anywhere else to write this feedback. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's just make sure the latest commit (a test commit) isn't added.
Please dismiss once the commit is removed
280aefa
to
aabda57
Compare
I'm merging this one as I want it tested as part of CR1. I suggest we start a more general discussion about multitenancy in the mailing list. |
Sorry, was off for some days. @gsmet You should take a closer look at the history of #8545 where you were explicitly asked to do a review.., |
Yes, that was the idea.
Why is it not simple? It is exactly doing what is described in the Hibernate manuals:
Unfortunately the Hibernate Multitenancy feature isn't finalized since years. As stated in the manual "The JPA expert group is in the process of defining multitenancy support for an upcoming version of the specification".
What is wong about it?
Might be right. Any suggestions to do it better are highly welcome.
That is not correct. The information is also used to generate the schema with Flyway, which is different for database and schema based multitenany (see Quickstart example)
This would not be any way better if you let the user "configure it by properties as they usually would in Hibernate".
Please go ahead and make a suggestion on how to do it.
I think the current solution is very easy for end users. Simply add the resolver and configure your data sources. But I'm open to any suggestions on how to do it better. |
Sorry, I should have mentioned that I opened #11861 to discuss this idea. |
I have to add more tests to fully test it but given the timeframe, it would be nice if @geoand and @machi1990 could have a look to what I did.
/cc @michael-schnell
Michael, I have some questions for you, could you please ping me when you're available? Thanks!