-
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
[WIP] QUARKUS-3363 - Offline startup for Hibernate ORM in Quarkus #43396
base: main
Are you sure you want to change the base?
Conversation
Thanks for your pull request! Your pull request does not follow our editorial rules. Could you have a look?
This message is automatically generated by a bot. |
🎊 PR Preview 11f6c5b has been successfully built and deployed to https://quarkus-pr-main-43396-preview.surge.sh/version/main/guides/
|
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.
Thanks! I added a few comments below, we can discuss on Zulip if you want.
Regarding documentation, it would probably make sense to add a subsection under "Dialects > Supported databases"; see here for the source, here for the rendered version for this PR (updates take a few minutes/hours after you push).
Note the subsection we'd add to the documentation does not need to list all configuration properties -- that's already done in this automatically-generated list. We would just need to mention that some dialects can be configured in more details to match the DB configuration, and link to the list.
Regarding tests, I think your only solution ATM would be to add something under integration-tests/jpa-oracle
, and integration-tests/jpa-mysql
, and so on.
You can take inspiration from DefaultSchemaTest
for your test; I picked this as an example because it overrides some settings compared to other tests, which I think you will need to do. Relevant classes:
DefaultSchemaTest
DefaultSchemaInGraalITCase
(same test extending the first, but run in native mode)main package with the entity and REST resource being tested: yes it's a bit weird, but that's how we can test even a native image, where the binary cannot (reasonably) run JUnit by itself.
EDIT: Actually, since we're talking about build-time properties here, this won't work. I think your only option would be to add a second persistence unit to application.properties
. You may need to have this new PU start offline if the settings you need to test won't work with the DB we test against -- but that's no big deal, as you mainly want to make sure the Dialect's state matches the settings you set.
Starting a PU offline will require an additional config property though, to explicitly ask Hibernate ORM to "start offline"... which was the point of #13522, and the reason we're introducing all these dialect-specific settings.
...orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/CockroachDialectConfig.java
Outdated
Show resolved
Hide resolved
...ent/src/main/java/io/quarkus/hibernate/orm/deployment/HibernateOrmConfigPersistenceUnit.java
Outdated
Show resolved
Hide resolved
/** | ||
* Configuration specific to the Hibernate ORM {@linkplain org.hibernate.dialect.MySQLDialect} | ||
*/ | ||
MySQLDialectConfig mysql(); |
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.
Note we have use dedicated configuration for MariaDB in Quarkus, e.g. there is a db-kind
named mariadb
, distinct from mysql
. It would probably make sense to do the same here?
FWIW you might be able to use inheritance with config groups if you want to avoid duplicating code... I think Guillaume added that support in his recent changes to the config annotation processor. We'll need to double checked by having a look at the resulting documentation, and of course through tests.
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 could just add MySQLDialectConfig mariadb();
, no?
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.
True, for now this would work.
...-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/HibernateOrmProcessor.java
Outdated
Show resolved
Hide resolved
* Specifies the bytes per character to use based on the database's configured | ||
* <a href="https://dev.mysql.com/doc/refman/8.0/en/charset-charsets.html">charset</a>. | ||
* | ||
* @see org.hibernate.cfg.DialectSpecificSettings#MYSQL_BYTES_PER_CHARACTER |
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.
Note:
- Such links won't appear in generated documentation.
- Application users are unlikely to reach this javadoc directly, they'll most likely read the rendered version included in the Quarkus documentation -- and in IDE plugins.
That's why we tend to do things like this:
Lines 88 to 90 in eeaecac
* Refer to | |
* link:{hibernate-orm-docs-url}#basic-uuid[this section of the Hibernate ORM documentation] | |
* to see the possible UUID representations. |
Reminder that Asciidoc syntax requires
@asciidoctlet
in the Javadoc comment.
hibernate-orm-docs-url
is defined here, in case you want to add links to Hibernate ORM Javadocs -- but since nowadays you have a list of documentation properties in the Hibernate ORM user guide, I guess it could be more practical to link directly there?
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.
Reminder that Asciidoc syntax requires @asciidoctlet in the Javadoc comment.
+1, sure just have not been using asciidoc formatting yet. But clearly I will need to start :)
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.
but since nowadays you have a list of documentation properties in the Hibernate ORM user guide, I guess it could be more practical to link directly there?
I think that's a good idea, Currently we don't generate url anchors for each setting as we'd need to, but https://hibernate.atlassian.net/browse/HHH-18654
...te-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/OracleDialectConfig.java
Outdated
Show resolved
Hide resolved
0a3dade
to
46aa8b3
Compare
} | ||
|
||
private static SupportedDatabaseKind determineDatabaseKind(String name) { | ||
if ( name.contains( "db2" ) ) { |
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.
DatabaseKind.isDB2(name)
seems more appropriate? Same for others.
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.
No, because this is also called with the Dialect 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.
I think this will not work well for db-kind
then, because some database kinds (e.g. postgresql
) have more than one corresponding string (e.g. pg
). You'll probably need two different classes.
For what it's worth, we already have code that infers the "db product name" (the Hibernate ORM one) from the explicit dialect here:
Lines 1137 to 1141 in c09e69a
if (dbKind.isPresent() && DatabaseKind.is(dbKind.get(), item.getDbKind()) | |
// Set the default version based on the dialect when we don't have a datasource | |
// (i.e. for database multi-tenancy) | |
|| explicitDialect.isPresent() && item.getMatchingDialects().contains(explicitDialect.get())) { | |
dbProductName = item.getDatabaseProductName(); |
So maybe you should base your code on this dbProductName
instead?
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 think this will not work well for db-kind then, because some database kinds (e.g. postgresql) have more than one corresponding string (e.g. pg).
Look at the callers. One works with a passed "database kind" and manually does the normalize which handles the case you were talking about (multiple names). The other works with the Dialect name.
So maybe you should base your code on this dbProductName instead?
Maybe, I'll take a look.
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.
Currently this code handles (1) db-kind and (2) explicit Dialect name.
Are you saying that it is legal to specify a dbProductName but not db-kind?
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.
So the "problem" with using dbProductName is that, unless Quarkus does this somewhere, there is no simple mapping of dbProductName to Dialect or SupportedDatabaseKind.
Assuming that it is legal to have just dbProductName without either db-kind or dialect, we'd need a method that handles mapping dbProductName to a SupportedDatabaseKind
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 is no simple mapping of dbProductName to Dialect or SupportedDatabaseKind
Well, actually, I could leverage org.hibernate.dialect.Database
to implement this...
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.
Ok, I added handling based on database product name as well.
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.
Thanks. Then if tests pass, we're all set.
FYI, the only way the database product name can be missing is if someone has no assigned datasource (because it's dynamic, see database multi-tenancy). Even then, users will need to set a dialect explicitly, and as long as they use one of the "standard" dialects, the database product name will be inferred from that dialect.
Was the integration test I added run? I'm not sure which Action check runs those integration tests. |
CI does not run on drafts, you need to mark as ready for review and add |
Though the recommended way of working if your code is not ready for review is to run GitHub Actions in your fork instead. |
This comment has been minimized.
This comment has been minimized.
Handle Hibernate's `DialectSpecificSettings` as supported Quarkus settings
Handle Hibernate's `DialectSpecificSettings` as supported Quarkus settings
72a6447
to
a97c74f
Compare
This comment has been minimized.
This comment has been minimized.
Um, I ran the formatter before I pushed. Even now, locally, I run the formatter and nothing changes. What do I need to do here? I find it strange that the IJ format stuff does not handle this either? |
How did you format code? The formatter does not handle import order, that's a different setting. If you installed the Eclipse Formatter plugin, you need to point to the import order config explicitly, it's a different file. |
I followed the directions from CONTRIBUTING :
|
I "format" using |
I suppose the formatting plugin failed and suggested it. Here it's another plugin failing. To run formatting + import sorting: Line 273 in 4eee652
Or if you want to limit to one module:
|
This part should have ensured that imports get sorted when you run auto-formatting in your IDE:
There something wrong if CTRL+ALT+O / CTRL+ALT+L still doesn't format code correctly... |
Handle Hibernate's `DialectSpecificSettings` as supported Quarkus settings - test for mariadb
14b5d3c
to
981a79e
Compare
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.
Hey @sebersole , sorry I left this aside... were you waiting for feedback from me?
From what I can see you finished implementing most setting, and were trying to run tests.
Though I suspect in order to run tests, we will need to introduce the config property that QUARKUS-3363 actually is about (the dialect config just happens to be a prerequisite): something that tells Hibernate ORM to start offline, i.e. that sets hibernate.boot.allow_jdbc_metadata_access
to false
(on runtime startup), and probably triggers exceptions if users requested automatic schema creation/update/validation.
quarkus.hibernate."offline".mariadb.bytesPerCharacter=1 | ||
quarkus.hibernate."offline".mariadb.noBackslashEscapes=true | ||
quarkus.hibernate."offline".mariadb.storageEngine=MY_CUSTOM_ENGINE |
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.
quarkus.hibernate."offline".mariadb.bytesPerCharacter=1 | |
quarkus.hibernate."offline".mariadb.noBackslashEscapes=true | |
quarkus.hibernate."offline".mariadb.storageEngine=MY_CUSTOM_ENGINE | |
quarkus.hibernate-orm."offline".mariadb.bytesPerCharacter=1 | |
quarkus.hibernate-orm."offline".mariadb.noBackslashEscapes=true | |
quarkus.hibernate-orm."offline".mariadb.storageEngine=MY_CUSTOM_ENGINE |
https://issues.redhat.com/browse/QUARKUS-3363
Fixes #13522
Handle ORM DialectSpecificSettings