HHH-17082 - Improve documentation of configuration settings

https://hibernate.atlassian.net/browse/HHH-17082
This commit is contained in:
Steve Ebersole 2023-08-15 13:38:31 -05:00
parent 7dc458f663
commit fd961cebb1
77 changed files with 5324 additions and 6467 deletions

View File

@ -200,28 +200,34 @@ def aggregateJavadocsTask = tasks.register( "aggregateJavadocs", Javadoc ) {
inputs.property "ormVersion", project.ormVersion inputs.property "ormVersion", project.ormVersion
destinationDir = mkdir( layout.buildDirectory.file( 'javadocs' ) ) destinationDir = mkdir( layout.buildDirectory.file( 'javadocs' ) )
source = configurations.javadocSources
source configurations.javadocSources classpath = configurations.javadocClasspath
classpath += configurations.javadocClasspath
// exclude any generated sources and internal packages // exclude any generated sources and internal packages
exclude '**/generated-src/**' exclude '**/generated-src/**'
exclude '**/internal/**' exclude '**/internal/**'
include '**/*.java' include '**/*.java'
maxMemory = '512m'
final int currentYear = new GregorianCalendar().get( Calendar.YEAR ) final int currentYear = new GregorianCalendar().get( Calendar.YEAR )
// apply standard config
maxMemory = '512m'
configure( options ) { configure( options ) {
overview = 'src/javadoc/overview.html' overview = 'src/main/javadoc/overview.html'
stylesheetFile = project.file( 'src/javadoc/stylesheet.css' ) stylesheetFile = project.file( 'src/main/javadoc/stylesheet.css' )
windowTitle = 'Hibernate JavaDocs' windowTitle = 'Hibernate Javadocs'
docTitle = "Hibernate JavaDoc ($project.version)" docTitle = "Hibernate Javadoc ($project.version)"
bottom = "Copyright &copy; 2001-$currentYear <a href=\"https://redhat.com\">Red Hat, Inc.</a> All Rights Reserved." bottom = "Copyright &copy; 2001-$currentYear <a href=\"https://redhat.com\">Red Hat, Inc.</a> All Rights Reserved."
use = true use = true
options.encoding = 'UTF-8' encoding = 'UTF-8'
tags(
'todo:X',
'apiNote:a:API Note:',
'implSpec:a:Implementation Specification:',
'implNote:a:Implementation Note:',
'settingDefault:f:Default Value:'
)
links = [ links = [
'https://docs.oracle.com/en/java/javase/11/docs/api/', 'https://docs.oracle.com/en/java/javase/11/docs/api/',
@ -231,14 +237,14 @@ def aggregateJavadocsTask = tasks.register( "aggregateJavadocs", Javadoc ) {
'https://www.javadoc.io/doc/javax.cache/cache-api/1.0.0/' 'https://www.javadoc.io/doc/javax.cache/cache-api/1.0.0/'
] ]
options.addStringOption( 'Xdoclint:none', '-quiet' ) addStringOption( 'Xdoclint:none', '-quiet' )
//
if ( jdkVersions.explicit ) { // if ( jdkVersions.explicit ) {
options.setJFlags( // setJFlags(
getProperty( 'toolchain.javadoc.jvmargs' ).toString(). // getProperty( 'toolchain.javadoc.jvmargs' ).toString().
split( ' ' ).toList().findAll( { !it.isEmpty() } ) // split( ' ' ).toList().findAll( { !it.isEmpty() } )
) // )
} // }
} }
if ( jdkVersions.explicit ) { if ( jdkVersions.explicit ) {
@ -249,6 +255,18 @@ def aggregateJavadocsTask = tasks.register( "aggregateJavadocs", Javadoc ) {
} }
} }
} }
doFirst {
def javaLanguageVersion = javadocTool.present
? javadocTool.get().metadata.languageVersion
: JavaLanguageVersion.of( JavaVersion.current().name )
if ( javaLanguageVersion.asInt() > 11 ) {
println "`aggregateJavadocs` is being run with a JDK newer than version 11: \n" +
"\t* `stylesheet.css` will not be compatible\n" +
"\t* generating the User Guide settings fragment will not succeed"
}
}
} }
asciidoctorj { asciidoctorj {
@ -480,30 +498,119 @@ def renderQueryLanguageGuidesTask = tasks.register( 'renderQueryLanguageGuides'
// User Guide ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // User Guide ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
settingsDocumentation { settingsDocumentation {
anchorNameBase = "settings"
sections { sections {
core { compliance {
settingsClassName = "org.hibernate.cfg.AvailableSettings" explicitPosition = 1
projectPath = ":hibernate-core" summary = "Jakarta Persistence Compliance Settings"
description = "Settings which control various aspects of compliance with the Jakarta Persistence specification "
settingsClassName "org.hibernate.cfg.JpaComplianceSettings"
}
persistence {
explicitPosition = 2
summary = "Persistence Unit Settings"
description = "Settings related to the creation and configuration of a persistence-unit - SessionFactory and EntityManagerFactory"
settingsClassName "org.hibernate.cfg.PersistenceSettings"
}
jdbc {
explicitPosition = 3
summary = "JDBC Settings"
description = "Settings which control various aspects of how Hibernate interacts with JDBC"
settingsClassName "org.hibernate.cfg.JdbcSettings"
}
c3p0 {
explicitPosition = 4
summary = "C3P0 Connection Pool Settings"
description = "Settings related to integrating with the C3P0 Connection pool"
settingsClassName "org.hibernate.cfg.C3p0Settings"
}
proxool {
explicitPosition = 5
summary = "Proxool Connection Pool Settings"
description = "Settings related to integrating with the Proxool Connection pool"
settingsClassName "org.hibernate.cfg.ProxoolSettings"
}
mapping {
explicitPosition = 6
summary = "Domain Mapping Settings"
description = "Settings which control how domain mappings are handled"
settingsClassName "org.hibernate.cfg.MappingSettings"
}
environment {
summary = "Runtime Environment Settings"
description = "Settings related to JNDI and ClassLoaders"
settingsClassName "org.hibernate.cfg.EnvironmentSettings"
}
schema {
summary = "Schema Tooling Settings"
description = "Settings which control the creation, dropping, update and validation of database schemas"
settingsClassName "org.hibernate.cfg.SchemaToolingSettings"
}
bytecode {
summary = "Bytecode Manipulation Settings"
description = "Settings which control Hibernate's BytecodeProvider used for bytecode manipulation"
settingsClassName "org.hibernate.cfg.BytecodeSettings"
}
cache {
summary = "Second-level Cache Settings"
description = "Settings which control Hibernate's second-level caching"
settingsClassName "org.hibernate.cfg.CacheSettings"
settingsClassName "org.hibernate.cache.jcache.ConfigSettings"
}
query {
summary = "Query Settings"
description = "Settings which control various parts of Hibernate's Query handling"
settingsClassName "org.hibernate.cfg.QuerySettings"
}
stats {
summary = "Statistics Settings"
description = "Settings which control the collection of statistics"
settingsClassName "org.hibernate.cfg.StatisticsSettings"
}
validation {
summary = "Jakarta Validation Integeration Settings"
description = "Settings used in the integration of Jakarta Validation"
settingsClassName "org.hibernate.cfg.ValidationSettings"
} }
envers { envers {
settingsClassName = "org.hibernate.envers.configuration.EnversSettings" summary = "Audit/History Settings"
projectPath = ":hibernate-envers" description = "Settings which control Hibernate's audit/history support (hibernate-envers)"
settingsClassName "org.hibernate.envers.configuration.EnversSettings"
} }
jcache { spatial {
settingsClassName = "org.hibernate.cache.jcache.ConfigSettings" summary = "Hibernate Spatial Settings"
projectPath = ":hibernate-jcache" description = "Settings which control Hibernate's support for spatial data (hibernate-spatial)"
settingsClassName "org.hibernate.spatial.HibernateSpatialConfigurationSettings"
settingsClassName "org.hibernate.spatial.integration.SpatialService"
}
misc {
summary = "Miscellaneous Settings"
description = "Miscellaneous Settings"
settingsClassName "org.hibernate.cfg.AvailableSettings"
} }
} }
} }
def generateSettingsDocTask = tasks.named( "generateSettingsDoc" ) { def generateSettingsDocTask = tasks.named( "generateSettingsDoc" ) {
dependsOn aggregateJavadocsTask dependsOn aggregateJavadocsTask
doFirst {
def javadoc = aggregateJavadocsTask.get()
def javaLanguageVersion = javadoc.javadocTool.present
? javadoc.javadocTool.get().metadata.languageVersion
: JavaLanguageVersion.of( JavaVersion.current().name )
if ( javaLanguageVersion.asInt() > 11 ) {
println "`aggregateJavadocs` was run with a JDK newer than version 11; generating the settings User Guide fragment will not succeed"
}
}
} }
def renderUserGuideHtmlTask = tasks.register( 'renderUserGuideHtml', AsciidoctorTask ) { task -> def renderUserGuideHtmlTask = tasks.register( 'renderUserGuideHtml', AsciidoctorTask ) { task ->
group = "Documentation" group = "Documentation"
description = 'Renders the User Guides in HTML format using Asciidoctor.' description = 'Renders the User Guides in HTML format using Asciidoctor.'
inputs.property "hibernate-version", project.ormVersion inputs.property "hibernate-version", project.ormVersion
inputs.file( generateSettingsDocTask.get().outputFile )
dependsOn generateSettingsDocTask dependsOn generateSettingsDocTask

View File

@ -1,6 +1,5 @@
== References
[bibliography] [bibliography]
== References
- [[[PoEAA]]] Martin Fowler. https://www.martinfowler.com/books/eaa.html[Patterns of Enterprise Application Architecture]. - [[[PoEAA]]] Martin Fowler. https://www.martinfowler.com/books/eaa.html[Patterns of Enterprise Application Architecture].
Addison-Wesley Professional. 2002. Addison-Wesley Professional. 2002.
- [[[JPwH]]] Christian Bauer & Gavin King. https://www.manning.com/books/java-persistence-with-hibernate-second-edition[Java Persistence with Hibernate, Second Edition]. Manning Publications Co. 2015. - [[[JPwH]]] Christian Bauer & Gavin King. https://www.manning.com/books/java-persistence-with-hibernate-second-edition[Java Persistence with Hibernate, Second Edition]. Manning Publications Co. 2015.

View File

@ -1,7 +0,0 @@
:documentation-project-dir: ../../../..
:root-project-dir: {documentation-project-dir}/..
[[settings-ref]]
== List of all available configuration settings
include::{documentation-project-dir}/target/asciidoc/fragments/config-settings.adoc[]

View File

@ -39,17 +39,13 @@ include::chapters/beans/Beans.adoc[]
include::chapters/portability/Portability.adoc[] include::chapters/portability/Portability.adoc[]
include::chapters/statistics/Statistics.adoc[] include::chapters/statistics/Statistics.adoc[]
include::chapters/tooling/Tooling.adoc[] include::chapters/tooling/Tooling.adoc[]
include::appendices/Configurations.adoc[]
include::appendices/Annotations.adoc[]
include::appendices/BestPractices.adoc[] include::appendices/BestPractices.adoc[]
include::appendices/Legacy_Bootstrap.adoc[]
include::appendices/Legacy_DomainModel.adoc[]
include::appendices/LegacyBasicTypeResolution.adoc[]
include::appendices/Legacy_Native_Queries.adoc[]
include::Credits.adoc[] include::Credits.adoc[]
include::ConfigPropertyList.adoc[] include::appendices/SettingsReference.adoc[]
include::appendices/LegacyBasicTypeResolution.adoc[]
include::appendices/Legacy_Native_Queries.adoc[]
include::Bibliography.adoc[] include::Bibliography.adoc[]

View File

@ -258,8 +258,3 @@ For this reason, `NONSTRICT_READ_WRITE` is not very suitable if entities are cha
When using clustering, the second-level cache entries are spread across multiple nodes. When using clustering, the second-level cache entries are spread across multiple nodes.
When using https://infinispan.org/blog/2015/10/01/hibernate-second-level-cache/[Infinispan distributed cache], only `READ_WRITE` and `NONSTRICT_READ_WRITE` are available for read-write caches. When using https://infinispan.org/blog/2015/10/01/hibernate-second-level-cache/[Infinispan distributed cache], only `READ_WRITE` and `NONSTRICT_READ_WRITE` are available for read-write caches.
Bear in mind that `NONSTRICT_READ_WRITE` offers a weaker consistency guarantee since stale updates are possible. Bear in mind that `NONSTRICT_READ_WRITE` offers a weaker consistency guarantee since stale updates are possible.
[NOTE]
====
For more about Hibernate Performance Tuning, check out the https://www.youtube.com/watch?v=BTdTEe9QL5k&amp;t=1s[High-Performance Hibernate] presentation from Devoxx France.
====

View File

@ -4,6 +4,7 @@
:extrasdir: extras :extrasdir: extras
:originalextrasdir: ../chapters/domain/extras :originalextrasdir: ../chapters/domain/extras
[appendix]
[[basic-legacy]] [[basic-legacy]]
== Legacy BasicType resolution == Legacy BasicType resolution

View File

@ -1,49 +0,0 @@
[[appendix-legacy-domain-model]]
== Legacy Domain Model
:sourcedir: extras
.Declaring a version property in `hbm.xml`
====
[source,xml]
----
include::{sourcedir}/version_property.xml[]
----
====
[cols=",",]
|=======================================================================
|column |The name of the column holding the version number. Optional, defaults to the property name.
|name |The name of a property of the persistent class.
|type |The type of the version number. Optional, defaults to `integer`.
|access |Hibernate's strategy for accessing the property value. Optional, defaults to `property`.
|unsaved-value |Indicates that an instance is newly instantiated and thus unsaved.
This distinguishes it from detached instances that were saved or loaded in a previous session.
The default value, `undefined`, indicates that the identifier property value should be used. Optional.
|generated |Indicates that the version property value is generated by the database. Optional, defaults to `never`.
|insert |Whether or not to include the `version` column in SQL `insert` statements.
Defaults to `true`, but you can set it to `false` if the database column is defined with a default value of `0`.
|=======================================================================
.The timestamp element in `hbm.xml`
====
[source,xml]
----
include::{sourcedir}/timestamp_version.xml[]
----
====
[cols=",",]
|=======================================================================
|column |The name of the column which holds the timestamp. Optional, defaults to the property name
|name |The name of a JavaBeans style property of Java type `Date` or `Timestamp` of the persistent class.
|access |The strategy Hibernate uses to access the property value. Optional, defaults to `property`.
|unsaved-value |A version property which indicates that the instance is newly instantiated and unsaved.
This distinguishes it from detached instances that were saved or loaded in a previous session.
The default value of `undefined` indicates that Hibernate uses the identifier property value.
|source |Whether Hibernate retrieves the timestamp from the database or the current JVM.
Database-based timestamps incur an overhead because Hibernate needs to query the database each time to determine the incremental next value.
However, database-derived timestamps are safer to use in a clustered environment.
Not all database dialects are known to support the retrieval of the database's current timestamp.
Others may also be unsafe for locking because of lack of precision.
|generated |Whether the timestamp property value is generated by the database. Optional, defaults to `never`.
|=======================================================================

View File

@ -1,3 +1,4 @@
[appendix]
[[appendix-legacy-native-queries]] [[appendix-legacy-native-queries]]
== Legacy Hibernate Native Queries == Legacy Hibernate Native Queries

View File

@ -0,0 +1,27 @@
[appendix]
[[settings]]
== Configuration Settings
Configuration settings can be broadly broken down into 3 categories -
Jakarta Persistence::
Settings which are standardized by the Jakarta Persistence specification for configuring any persistence provider. These
settings are defined by the `jakarta.persistence.` namespace
Hibernate::
Hibernate-specific settings which control various Hibernate behaviors which are extensions to or outside the scope
of the Jakarta Persistence specification. These settings are defined by the `hibernate.` namespace
Legacy JPA::
Settings which were standardized by Java Persistence, the legacy version of the Jakarta Persistence specification
(prior to version 3.1). These settings are defined by the `javax.persistence.` namespace
[NOTE]
====
For the time being, Hibernate continues to support the legacy Java Persistence settings in addition to
the Jakarta Persistence forms. Applications should strongly consider migrating to the new Jakarta Persistence
as support for the legacy Java Persistence will likely be removed at some point.
For (legacy) Hibernate settings which have a direct Jakarta Persistence corollary, the Jakarta Persistence
form should be preferred - e.g. `hibernate.connection.driver_class` -> `jakarta.persistence.jdbc.driver`.
====
include::../../../../../target/asciidoc/fragments/config-settings.adoc[]

View File

@ -13,7 +13,7 @@ The process is very different for each.
[TIP] [TIP]
==== ====
During the bootstrap process, you might want to customize Hibernate behavior so make sure you check the <<appendices/Configurations.adoc#configurations,Configurations>> section as well. During the bootstrap process, you might want to customize Hibernate behavior so make sure you check the <<appendices/SettingsReference.adoc#settings>> section as well.
==== ====
[[bootstrap-native]] [[bootstrap-native]]

View File

@ -1,5 +1,5 @@
[[events]] [[events]]
== Interceptors and events == Interceptors and Events
:root-project-dir: ../../../../../../.. :root-project-dir: ../../../../../../..
:core-project-dir: {root-project-dir}/hibernate-core :core-project-dir: {root-project-dir}/hibernate-core
:example-dir-event: {core-project-dir}/src/test/java/org/hibernate/orm/test/events :example-dir-event: {core-project-dir}/src/test/java/org/hibernate/orm/test/events

View File

@ -1,5 +1,5 @@
[[database]] [[database]]
== Database access == Database Access
[[database-connectionprovider]] [[database-connectionprovider]]
=== ConnectionProvider === ConnectionProvider

View File

@ -12,8 +12,8 @@ Generally, it does this when the application:
All of these JNDI calls route through a single service whose role is `org.hibernate.engine.jndi.spi.JndiService`. All of these JNDI calls route through a single service whose role is `org.hibernate.engine.jndi.spi.JndiService`.
The standard `JndiService` accepts a number of configuration settings: The standard `JndiService` accepts a number of configuration settings:
`hibernate.jndi.class`:: names the `javax.naming.InitialContext` implementation class to use. See https://docs.oracle.com/javase/8/docs/api/javax/naming/Context.html#INITIAL_CONTEXT_FACTORY[`javax.naming.Context#INITIAL_CONTEXT_FACTORY`] * <<settings-hibernate.jndi.class, hibernate.jndi.class>>
`hibernate.jndi.url`:: names the JNDI InitialContext connection url. See https://docs.oracle.com/javase/8/docs/api/javax/naming/Context.html#PROVIDER_URL[`javax.naming.Context.PROVIDER_URL`] * <<settings-hibernate.jndi.url, hibernate.jndi.url>>
Any other settings prefixed with `hibernate.jndi.` will be collected and passed along to the JNDI provider. Any other settings prefixed with `hibernate.jndi.` will be collected and passed along to the JNDI provider.

View File

@ -1,5 +1,5 @@
[[schema-generation]] [[schema-generation]]
== Schema generation == Schema Generation
:root-project-dir: ../../../../../../.. :root-project-dir: ../../../../../../..
:core-project-dir: {root-project-dir}/hibernate-core :core-project-dir: {root-project-dir}/hibernate-core
:example-dir-schemagen: {core-project-dir}/src/test/java/org/hibernate/orm/test/schema :example-dir-schemagen: {core-project-dir}/src/test/java/org/hibernate/orm/test/schema

View File

@ -1,5 +1,5 @@
[[transactions]] [[transactions]]
== Transactions and concurrency control == Transactions
:root-project-dir: ../../../../../../.. :root-project-dir: ../../../../../../..
:core-project-dir: {root-project-dir}/hibernate-core :core-project-dir: {root-project-dir}/hibernate-core
:example-dir-transaction: {core-project-dir}/src/test/java/org/hibernate/orm/test/transactions :example-dir-transaction: {core-project-dir}/src/test/java/org/hibernate/orm/test/transactions

View File

@ -6,7 +6,7 @@
--> -->
<body> <body>
<h2>Hibernate ORM aggregated API documentation</h2> <h2>Hibernate ORM Javadocs</h2>
<p> <p>
Hibernate is a library for object/relation mapping (ORM). It provides: Hibernate is a library for object/relation mapping (ORM). It provides:

View File

@ -1,83 +0,0 @@
Status of the documentation overhaul (5.0 version)
==================================================
Overall the plan is to define 3 DocBook-based guides. The intention is for this document to serve
as an outline of the work and a status of what still needs done.
NOTE : entries marked with <strike>strike-through</strike> indicate that the content is believed to be done; review
would still be appreciated.
User Guide
==========
Covers reference topics targeting users.
* <strike>Prefix</strike>
* <strike>Architecture</strike>
* <strike>DomainModel</strike>
* <strike>Bootstrap</strike>
* <strike>PersistenceContext</strike>
* <strike>Database_Access</strike>
* <strike>Transactions</strike>
* <strike>JNDI</strike>
* Fetching - still need to document batch fetching, subselect fetching, extra laziness and EntityGraphs
* Flushing (to be written)
* Cascading (needs lots of work)
* Locking (needs some work)
* Batching (needs lot of work - not started - open questions)
* Caching (needs some work)
* Events (need some work)
* <strike>Query - HQL/JPQL</strike>
* <strike>Query - Criteria</strike>
* <strike>Query - Native (copy from old)</strike>
* Multi_Tenancy (needs some work)
* OSGi (right place for this?)
* Envers (right place for this?)
* Portability (needs some work)
Domain Model Mapping Guide
===========================
Covers mapping domain model to database. Note that a lot of the "not started" content exists elsewhere; its merely a
matter of pulling that content in and better organizing it.
* <strike>Prefix</strike>
* <strike>Data_Categorizations</strike>
* Entity (needs some work)
* <strike>Basic_Types</strike>
* <strike>Composition</strike>
* <strike>Collection (needs some work)
* Identifiers (mostly done - needs "derived id" stuff documented)
* <strike>Natural_Id</strike>
* Secondary_Tables (not started) - logically a joined in-line view
* Associations (not started)
* Attribute_Access (not started)
* Mapping_Overrides - AttributeOverrides/AssociationOverrides (not started)
* Generated_attributes (not started)
* "columns, formulas, read/write-fragments" (not started)
* Naming_Strategies - implicit, physical, quoting (not started)
* Database_Constraints - pk, fk, uk, check, etc (not started)
* Auxiliary_DB_Objects - does this belong here? or somewhere else (integrations guide) discussing schema tooling?
Integrations Guide
===================
* Services&Registries (pretty much done)
* IdGeneratorStrategyInterpreter (not started)
* custom Session/SessionFactory implementors (not started)
* ???
Overall
=======
* I really like the idea of each chapter having a title+abstract. See userGuide/chapters/HQL.xml
for an example.
* I really like the idea of each chapter having a "Related Topics" (?)sidebar(?). See
userGuide/chapters/HQL.xml for an example. I am not sure `<sidebar/>` is the best element for
this concept, but I could not find a better one on cursory glance. I noticed `literallayout` used in
a few DocBook examples for something similar.

View File

@ -25,24 +25,30 @@ javadoc {
// Travis CI JDK 11 build did not like this // Travis CI JDK 11 build did not like this
// docletpath = configurations.asciidoclet.files.asType(List) // docletpath = configurations.asciidoclet.files.asType(List)
// doclet = 'org.asciidoctor.Asciidoclet' // doclet = 'org.asciidoctor.Asciidoclet'
overview = 'src/main/javadoc/overview.html'
stylesheetFile = project.file( 'src/main/javadoc/stylesheet.css' )
windowTitle = "$project.name JavaDocs" windowTitle = "$project.name JavaDocs"
docTitle = "$project.name JavaDocs ($project.version)" docTitle = "$project.name JavaDocs ($project.version)"
bottom = "Copyright &copy; 2001-$currentYear <a href=\"https://redhat.com\">Red Hat, Inc.</a> All Rights Reserved." bottom = "Copyright &copy; 2001-$currentYear <a href=\"https://redhat.com\">Red Hat, Inc.</a> All Rights Reserved."
use = true use = true
encoding = 'UTF-8' encoding = 'UTF-8'
links += [
links = [
'https://docs.oracle.com/en/java/javase/11/docs/api/', 'https://docs.oracle.com/en/java/javase/11/docs/api/',
'https://jakarta.ee/specifications/platform/9/apidocs/' 'https://jakarta.ee/specifications/bean-validation/3.0/apidocs/',
'https://jakarta.ee/specifications/cdi/4.0/apidocs/',
'https://jakarta.ee/specifications/platform/9/apidocs/',
'https://www.javadoc.io/doc/javax.cache/cache-api/1.0.0/'
] ]
tags = [ "apiNote", 'implSpec', 'implNote', 'todo' ]
addStringOption( 'Xdoclint:none', '-quiet' ) addStringOption( 'Xdoclint:none', '-quiet' )
tags( tags(
'todo:X"', 'todo:X',
'apiNote:a:"API Note:"', 'apiNote:a:API Note:',
'implSpec:a:"Implementation Specification:"', 'implSpec:a:Implementation Specification:',
'implNote:a:"Implementation Note:"' 'implNote:a:Implementation Note:',
'settingDefault:f:Default Value:'
) )
} }
} }

View File

@ -18,7 +18,8 @@ import com.mchange.v2.c3p0.DataSources;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException; import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
import org.hibernate.cfg.Environment; import org.hibernate.cfg.C3p0Settings;
import org.hibernate.cfg.JdbcSettings;
import org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator; import org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.internal.util.PropertiesHelper; import org.hibernate.internal.util.PropertiesHelper;
@ -31,6 +32,7 @@ import org.hibernate.service.spi.Stoppable;
import static org.hibernate.c3p0.internal.C3P0MessageLogger.C3P0_LOGGER; import static org.hibernate.c3p0.internal.C3P0MessageLogger.C3P0_LOGGER;
import static org.hibernate.c3p0.internal.C3P0MessageLogger.C3P0_MSG_LOGGER; import static org.hibernate.c3p0.internal.C3P0MessageLogger.C3P0_MSG_LOGGER;
import static org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator.extractSetting;
/** /**
* A connection provider that uses a C3P0 connection pool. Hibernate will use this by * A connection provider that uses a C3P0 connection pool. Hibernate will use this by
@ -41,6 +43,7 @@ import static org.hibernate.c3p0.internal.C3P0MessageLogger.C3P0_MSG_LOGGER;
*/ */
public class C3P0ConnectionProvider public class C3P0ConnectionProvider
implements ConnectionProvider, Configurable, Stoppable, ServiceRegistryAwareService { implements ConnectionProvider, Configurable, Stoppable, ServiceRegistryAwareService {
private static volatile String HIBERNATE_STYLE_SETTING_PREFIX = C3p0Settings.C3P0_CONFIG_PREFIX + ".";
//swaldman 2006-08-28: define c3p0-style configuration parameters for properties with //swaldman 2006-08-28: define c3p0-style configuration parameters for properties with
// hibernate-specific overrides to detect and warn about conflicting // hibernate-specific overrides to detect and warn about conflicting
@ -104,18 +107,28 @@ public class C3P0ConnectionProvider
@Override @Override
public void configure(Map<String, Object> props) { public void configure(Map<String, Object> props) {
final String jdbcDriverClass = (String) props.get( Environment.DRIVER ); final String jdbcDriverClass = extractSetting(
final String jdbcUrl = (String) props.get( Environment.URL ); props,
JdbcSettings.JAKARTA_JDBC_DRIVER,
JdbcSettings.DRIVER,
JdbcSettings.JPA_JDBC_DRIVER
);
final String jdbcUrl = extractSetting(
props,
JdbcSettings.JAKARTA_JDBC_URL,
JdbcSettings.URL,
JdbcSettings.JPA_JDBC_URL
);
final Properties connectionProps = ConnectionProviderInitiator.getConnectionProperties( props ); final Properties connectionProps = ConnectionProviderInitiator.getConnectionProperties( props );
C3P0_MSG_LOGGER.c3p0UsingDriver( jdbcDriverClass, jdbcUrl ); C3P0_MSG_LOGGER.c3p0UsingDriver( jdbcDriverClass, jdbcUrl );
C3P0_MSG_LOGGER.connectionProperties( ConfigurationHelper.maskOut( connectionProps, "password" ) ); C3P0_MSG_LOGGER.connectionProperties( ConfigurationHelper.maskOut( connectionProps, "password" ) );
autocommit = ConfigurationHelper.getBoolean( Environment.AUTOCOMMIT, props ); autocommit = ConfigurationHelper.getBoolean( JdbcSettings.AUTOCOMMIT, props );
C3P0_MSG_LOGGER.autoCommitMode( autocommit ); C3P0_MSG_LOGGER.autoCommitMode( autocommit );
if ( jdbcDriverClass == null ) { if ( jdbcDriverClass == null ) {
C3P0_MSG_LOGGER.jdbcDriverNotSpecified( Environment.DRIVER ); C3P0_MSG_LOGGER.jdbcDriverNotSpecified();
} }
else { else {
try { try {
@ -129,20 +142,20 @@ public class C3P0ConnectionProvider
try { try {
//swaldman 2004-02-07: modify to allow null values to signify fall through to c3p0 PoolConfig defaults //swaldman 2004-02-07: modify to allow null values to signify fall through to c3p0 PoolConfig defaults
final Integer minPoolSize = ConfigurationHelper.getInteger( Environment.C3P0_MIN_SIZE, props ); final Integer minPoolSize = ConfigurationHelper.getInteger( C3p0Settings.C3P0_MIN_SIZE, props );
final Integer maxPoolSize = ConfigurationHelper.getInteger( Environment.C3P0_MAX_SIZE, props ); final Integer maxPoolSize = ConfigurationHelper.getInteger( C3p0Settings.C3P0_MAX_SIZE, props );
final Integer maxIdleTime = ConfigurationHelper.getInteger( Environment.C3P0_TIMEOUT, props ); final Integer maxIdleTime = ConfigurationHelper.getInteger( C3p0Settings.C3P0_TIMEOUT, props );
final Integer maxStatements = ConfigurationHelper.getInteger( Environment.C3P0_MAX_STATEMENTS, props ); final Integer maxStatements = ConfigurationHelper.getInteger( C3p0Settings.C3P0_MAX_STATEMENTS, props );
final Integer acquireIncrement = ConfigurationHelper.getInteger( Environment.C3P0_ACQUIRE_INCREMENT, props ); final Integer acquireIncrement = ConfigurationHelper.getInteger( C3p0Settings.C3P0_ACQUIRE_INCREMENT, props );
final Integer idleTestPeriod = ConfigurationHelper.getInteger( Environment.C3P0_IDLE_TEST_PERIOD, props ); final Integer idleTestPeriod = ConfigurationHelper.getInteger( C3p0Settings.C3P0_IDLE_TEST_PERIOD, props );
final Properties c3props = new Properties(); final Properties c3props = new Properties();
// turn hibernate.c3p0.* into c3p0.*, so c3p0 // turn hibernate.c3p0.* into c3p0.*, so c3p0
// gets a chance to see all hibernate.c3p0.* // gets a chance to see all hibernate.c3p0.*
for ( String key : props.keySet() ) { for ( String key : props.keySet() ) {
if ( key.startsWith( "hibernate.c3p0." ) ) { if ( key.startsWith( HIBERNATE_STYLE_SETTING_PREFIX ) ) {
final String newKey = key.substring( 15 ); final String newKey = key.substring( HIBERNATE_STYLE_SETTING_PREFIX.length() );
if ( props.containsKey( newKey ) ) { if ( props.containsKey( newKey ) ) {
warnPropertyConflict( key, newKey ); warnPropertyConflict( key, newKey );
} }
@ -150,17 +163,13 @@ public class C3P0ConnectionProvider
} }
} }
setOverwriteProperty( Environment.C3P0_MIN_SIZE, C3P0_STYLE_MIN_POOL_SIZE, props, c3props, minPoolSize ); setOverwriteProperty( C3p0Settings.C3P0_MIN_SIZE, C3P0_STYLE_MIN_POOL_SIZE, props, c3props, minPoolSize );
setOverwriteProperty( Environment.C3P0_MAX_SIZE, C3P0_STYLE_MAX_POOL_SIZE, props, c3props, maxPoolSize ); setOverwriteProperty( C3p0Settings.C3P0_MAX_SIZE, C3P0_STYLE_MAX_POOL_SIZE, props, c3props, maxPoolSize );
setOverwriteProperty( Environment.C3P0_TIMEOUT, C3P0_STYLE_MAX_IDLE_TIME, props, c3props, maxIdleTime ); setOverwriteProperty( C3p0Settings.C3P0_TIMEOUT, C3P0_STYLE_MAX_IDLE_TIME, props, c3props, maxIdleTime );
setOverwriteProperty( C3p0Settings.C3P0_MAX_STATEMENTS, C3P0_STYLE_MAX_STATEMENTS, props, c3props, maxStatements );
setOverwriteProperty( C3p0Settings.C3P0_ACQUIRE_INCREMENT, C3P0_STYLE_ACQUIRE_INCREMENT, props, c3props, acquireIncrement );
setOverwriteProperty( setOverwriteProperty(
Environment.C3P0_MAX_STATEMENTS, C3P0_STYLE_MAX_STATEMENTS, props, c3props, maxStatements C3p0Settings.C3P0_IDLE_TEST_PERIOD,
);
setOverwriteProperty(
Environment.C3P0_ACQUIRE_INCREMENT, C3P0_STYLE_ACQUIRE_INCREMENT, props, c3props, acquireIncrement
);
setOverwriteProperty(
Environment.C3P0_IDLE_TEST_PERIOD,
C3P0_STYLE_IDLE_CONNECTION_TEST_PERIOD, C3P0_STYLE_IDLE_CONNECTION_TEST_PERIOD,
props, props,
c3props, c3props,

View File

@ -59,6 +59,8 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
public @interface BatchSize { public @interface BatchSize {
/** /**
* The maximum batch size, a strictly positive integer. * The maximum batch size, a strictly positive integer.
* <p/>
* Default is defined by {@link org.hibernate.cfg.FetchSettings#DEFAULT_BATCH_FETCH_SIZE}
*/ */
int size(); int size();
} }

View File

@ -17,7 +17,7 @@ import org.hibernate.service.spi.ServiceRegistryImplementor;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
import static org.hibernate.cfg.AvailableSettings.BYTECODE_PROVIDER; import static org.hibernate.cfg.BytecodeSettings.BYTECODE_PROVIDER;
public final class BytecodeProviderInitiator implements StandardServiceInitiator<BytecodeProvider> { public final class BytecodeProviderInitiator implements StandardServiceInitiator<BytecodeProvider> {

View File

@ -70,8 +70,8 @@ import net.bytebuddy.matcher.ElementMatchers;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
public class BytecodeProviderImpl implements BytecodeProvider { public class BytecodeProviderImpl implements BytecodeProvider {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( BytecodeProviderImpl.class ); private static final CoreMessageLogger LOG = CoreLogging.messageLogger( BytecodeProviderImpl.class );
private static final String INSTANTIATOR_PROXY_NAMING_SUFFIX = "HibernateInstantiator"; private static final String INSTANTIATOR_PROXY_NAMING_SUFFIX = "HibernateInstantiator";
private static final String OPTIMIZER_PROXY_NAMING_SUFFIX = "HibernateAccessOptimizer"; private static final String OPTIMIZER_PROXY_NAMING_SUFFIX = "HibernateAccessOptimizer";
private static final ElementMatcher.Junction<NamedElement> newInstanceMethodName = ElementMatchers.named( private static final ElementMatcher.Junction<NamedElement> newInstanceMethodName = ElementMatchers.named(

View File

@ -14,7 +14,6 @@ import org.hibernate.bytecode.enhance.spi.Enhancer;
import org.hibernate.bytecode.spi.BytecodeProvider; import org.hibernate.bytecode.spi.BytecodeProvider;
import org.hibernate.bytecode.spi.ProxyFactoryFactory; import org.hibernate.bytecode.spi.ProxyFactoryFactory;
import org.hibernate.bytecode.spi.ReflectionOptimizer; import org.hibernate.bytecode.spi.ReflectionOptimizer;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.property.access.spi.PropertyAccess; import org.hibernate.property.access.spi.PropertyAccess;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;

View File

@ -0,0 +1,73 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.cfg;
import java.sql.PreparedStatement;
import org.hibernate.engine.jdbc.batch.spi.BatchBuilder;
/**
* @author Steve Ebersole
*/
public interface BatchSettings {
/**
* Names the {@link BatchBuilder} implementation to use.
*
* @settingDefault Standard builder based on {@link #STATEMENT_BATCH_SIZE}
*/
String BUILDER = "hibernate.jdbc.batch.builder";
/**
* Specifies the maximum number of {@linkplain java.sql.PreparedStatement statements}
* to {@linkplain PreparedStatement#addBatch batch} together.
* <p/>
* A nonzero value enables batching
*
* @see java.sql.PreparedStatement#executeBatch
* @see java.sql.PreparedStatement#addBatch
* @see org.hibernate.boot.SessionFactoryBuilder#applyJdbcBatchSize
*
* @settingDefault 0
*/
String STATEMENT_BATCH_SIZE = "hibernate.jdbc.batch_size";
/**
* Enable ordering of update statements by primary key value, for the purpose of more
* efficient JDBC batching
*
* @see org.hibernate.boot.SessionFactoryBuilder#applyOrderingOfUpdates
*
* @settingDefault {@code false}
*/
String ORDER_UPDATES = "hibernate.order_updates";
/**
* Enable ordering of insert statements by primary key value, for the purpose of more
* efficient JDBC batching.
*
* @see org.hibernate.boot.SessionFactoryBuilder#applyOrderingOfInserts
*
* @settingDefault {@code false}
*/
String ORDER_INSERTS = "hibernate.order_inserts";
/**
* When enabled, specifies that {@linkplain jakarta.persistence.Version versioned}
* data should be included in batching.
*
* @see org.hibernate.boot.SessionFactoryBuilder#applyJdbcBatchingForVersionedEntities(boolean)
*
* @settingDefault Generally {@code true}, though can vary based on Dialect
*/
String BATCH_VERSIONED_DATA = "hibernate.jdbc.batch_versioned_data";
/**
* @deprecated Use {@link #BUILDER} instead
*/
@Deprecated
String BATCH_STRATEGY = "hibernate.jdbc.factory_class";
}

View File

@ -0,0 +1,46 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.cfg;
/**
* Settings which control the {@link org.hibernate.bytecode.spi.BytecodeProvider}
* used for bytecode enhancement and reflection optimization.
*
* @author Steve Ebersole
*/
public interface BytecodeSettings {
/**
* Selects a bytecode enhancement library.
* <p>
* At present only bytebuddy is supported, bytebuddy being the default since version 5.3.
*
* @settingDefault {@code "bytebuddy"}
*/
String BYTECODE_PROVIDER = "hibernate.bytecode.provider";
/**
* Enable association management feature in runtime bytecode enhancement
*
* @settingDefault {@code false}
*/
String ENHANCER_ENABLE_ASSOCIATION_MANAGEMENT = "hibernate.enhancer.enableAssociationManagement";
/**
* @deprecated Will be removed without replacement. See HHH-15641
*/
@Deprecated(forRemoval = true)
@SuppressWarnings("DeprecatedIsStillUsed")
String ENHANCER_ENABLE_DIRTY_TRACKING = "hibernate.enhancer.enableDirtyTracking";
/**
* @deprecated Will be removed without replacement. See HHH-15641
*/
@SuppressWarnings("DeprecatedIsStillUsed")
@Deprecated(forRemoval = true)
String ENHANCER_ENABLE_LAZY_INITIALIZATION = "hibernate.enhancer.enableLazyInitialization";
}

View File

@ -0,0 +1,48 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.cfg;
/**
* @author Steve Ebersole
*/
public interface C3p0Settings {
/**
* A setting prefix used to indicate settings that target the hibernate-c3p0 integration
*/
String C3P0_CONFIG_PREFIX = "hibernate.c3p0";
/**
* Maximum size of C3P0 connection pool
*/
String C3P0_MAX_SIZE = "hibernate.c3p0.max_size";
/**
* Minimum size of C3P0 connection pool
*/
String C3P0_MIN_SIZE = "hibernate.c3p0.min_size";
/**
* Maximum idle time for C3P0 connection pool
*/
String C3P0_TIMEOUT = "hibernate.c3p0.timeout";
/**
* Maximum size of C3P0 statement cache
*/
String C3P0_MAX_STATEMENTS = "hibernate.c3p0.max_statements";
/**
* Number of connections acquired when pool is exhausted
*/
String C3P0_ACQUIRE_INCREMENT = "hibernate.c3p0.acquire_increment";
/**
* Idle time before a C3P0 pooled connection is validated
*/
String C3P0_IDLE_TEST_PERIOD = "hibernate.c3p0.idle_test_period";
}

View File

@ -0,0 +1,241 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.cfg;
import org.hibernate.cache.internal.NoCachingRegionFactory;
import org.hibernate.cache.spi.RegionFactory;
import org.hibernate.cache.spi.TimestampsCacheFactory;
import org.hibernate.jpa.SpecHints;
/**
* Settings for Hibernate's second-level caching
*
* @author Steve Ebersole
*/
public interface CacheSettings {
/**
* When enabled, specifies that the second-level cache (which JPA calls the
* "shared" cache) may be used, as per the rules defined in JPA 2 section 3.1.7.
* <p>
* See JPA 2 sections 9.4.3 and 8.2.1.7
*
* @see jakarta.persistence.SharedCacheMode
*/
String JAKARTA_SHARED_CACHE_MODE = "jakarta.persistence.sharedCache.mode";
/**
* Set a default value for {@link SpecHints#HINT_SPEC_CACHE_RETRIEVE_MODE},
* used when the hint is not explicitly specified.
* <p>
* It does not usually make sense to change the default from
* {@link jakarta.persistence.CacheRetrieveMode#USE}.
*
* @see SpecHints#HINT_SPEC_CACHE_RETRIEVE_MODE
*/
String JAKARTA_SHARED_CACHE_RETRIEVE_MODE = SpecHints.HINT_SPEC_CACHE_RETRIEVE_MODE;
/**
* Set a default value for {@link SpecHints#HINT_SPEC_CACHE_STORE_MODE},
* used when the hint is not explicitly specified.
* <p>
* It does not usually make sense to change the default from
* {@link jakarta.persistence.CacheStoreMode#USE}.
*
* @see SpecHints#HINT_SPEC_CACHE_RETRIEVE_MODE
*/
String JAKARTA_SHARED_CACHE_STORE_MODE = SpecHints.HINT_SPEC_CACHE_STORE_MODE;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Hibernate settings
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* When enabled, specifies that the second-level cache may be used.
* <p>
* By default, if the configured {@link RegionFactory}
* is not the {@link org.hibernate.cache.internal.NoCachingRegionFactory}, then
* the second-level cache is enabled. Otherwise, the second-level cache is disabled.
*
* @settingDefault {@code true} when a {@linkplain #CACHE_REGION_FACTORY provider} is
* specified; {@code false} otherwise.
*
* @see #CACHE_REGION_FACTORY
* @see org.hibernate.boot.SessionFactoryBuilder#applySecondLevelCacheSupport(boolean)
*/
String USE_SECOND_LEVEL_CACHE = "hibernate.cache.use_second_level_cache";
/**
* Enable the query results cache
*
* @settingDefault {@code false}
*
* @see org.hibernate.boot.SessionFactoryBuilder#applyQueryCacheSupport(boolean)
*/
String USE_QUERY_CACHE = "hibernate.cache.use_query_cache";
/**
* The {@link RegionFactory} implementation, either:
* <ul>
* <li>an instance of {@link RegionFactory},
* <li>a {@link Class} implementing {@link RegionFactory}, or
* <li>he name of a class implementing {@link RegionFactory}.
* </ul>
* <p>
* Defaults to {@link NoCachingRegionFactory}, so that caching is disabled.
*
* @see #USE_SECOND_LEVEL_CACHE
*/
String CACHE_REGION_FACTORY = "hibernate.cache.region.factory_class";
/**
* Specifies the {@link org.hibernate.cache.spi.TimestampsCacheFactory} to use.
*
* @see org.hibernate.boot.SessionFactoryBuilder#applyTimestampsCacheFactory(TimestampsCacheFactory)
*/
String QUERY_CACHE_FACTORY = "hibernate.cache.query_cache_factory";
/**
* The {@code CacheProvider} region name prefix
*
* @see org.hibernate.boot.SessionFactoryBuilder#applyCacheRegionPrefix(String)
*/
String CACHE_REGION_PREFIX = "hibernate.cache.region_prefix";
/**
* Specifies the {@link org.hibernate.annotations.CacheConcurrencyStrategy} to use by
* default when an entity is marked {@link jakarta.persistence.Cacheable @Cacheable},
* but no concurrency strategy is explicitly specified via the
* {@link org.hibernate.annotations.Cache} annotation.
* <p>
* An explicit strategy may be specified using
* {@link org.hibernate.annotations.Cache#usage @Cache(usage=...)}.
*
* @settingDefault The cache provider's default strategy
*
* @see org.hibernate.boot.MetadataBuilder#applyAccessType(org.hibernate.cache.spi.access.AccessType)
* @see RegionFactory#getDefaultAccessType
*/
String DEFAULT_CACHE_CONCURRENCY_STRATEGY = "hibernate.cache.default_cache_concurrency_strategy";
/**
* Optimize interaction with the second-level cache to minimize writes, at the cost
* of an additional read before each write. This setting is useful if writes to the
* cache are much more expensive than reads from the cache, for example, if the cache
* is a distributed cache.
* <p>
* It's not usually necessary to set this explicitly because, by default, it's set
* to a {@linkplain org.hibernate.boot.SessionFactoryBuilder#applyMinimalPutsForCaching(boolean)
* sensible value} by the second-level cache implementation.
*
* @settingDefault The cache provider's default
*
* @see org.hibernate.boot.SessionFactoryBuilder#applyMinimalPutsForCaching(boolean)
* @see RegionFactory#isMinimalPutsEnabledByDefault()
*/
String USE_MINIMAL_PUTS = "hibernate.cache.use_minimal_puts";
/**
* Enables the use of structured second-level cache entries. This makes the cache
* entries human-readable, but carries a performance cost.
*
* @settingDefault {@code false}
*
* @see org.hibernate.boot.SessionFactoryBuilder#applyStructuredCacheEntries(boolean)
*/
String USE_STRUCTURED_CACHE = "hibernate.cache.use_structured_entries";
/**
* Enables the automatic eviction of a bidirectional association's collection
* cache when an element in the {@link jakarta.persistence.ManyToOne} collection
* is added, updated, or removed without properly managing the change on the
* {@link jakarta.persistence.OneToMany} side.
*
* @settingDefault {@code false}
*
* @see org.hibernate.boot.SessionFactoryBuilder#applyAutomaticEvictionOfCollectionCaches(boolean)
*/
String AUTO_EVICT_COLLECTION_CACHE = "hibernate.cache.auto_evict_collection_cache";
/**
* Enable direct storage of entity references into the second level cache when
* applicable. This is appropriate only for immutable entities.
* <p>
* By default, entities are always stored in a "disassembled" form, that is, as
* a tuple of attribute values.
*
* @settingDefault {@code false}
*
* @see org.hibernate.boot.SessionFactoryBuilder#applyDirectReferenceCaching(boolean)
*/
String USE_DIRECT_REFERENCE_CACHE_ENTRIES = "hibernate.cache.use_reference_entries";
/**
* Specifies the {@link org.hibernate.cache.spi.CacheKeysFactory} to use, either:
* <ul>
* <li>an instance of {@link org.hibernate.cache.spi.CacheKeysFactory},
* <li>a {@link Class} implementing {@link org.hibernate.cache.spi.CacheKeysFactory},
* <li>the name of a class implementing {@link org.hibernate.cache.spi.CacheKeysFactory},
* <li>{@code "default"} as a short name for {@link org.hibernate.cache.internal.DefaultCacheKeysFactory}, or
* <li>{@code "simple"} as a short name for {@link org.hibernate.cache.internal.SimpleCacheKeysFactory}.
* </ul>
*
* @since 5.2
*
* @deprecated this is only honored for {@code hibernate-infinispan}
*/
@Deprecated
@SuppressWarnings("DeprecatedIsStillUsed")
String CACHE_KEYS_FACTORY = "hibernate.cache.keys_factory";
/**
* Entity cache configuration properties follow the pattern
* {@code hibernate.classcache.packagename.ClassName usage[, region]}
* where {@code usage} is the cache strategy used and {@code region} the cache region name
*/
String CLASS_CACHE_PREFIX = "hibernate.classcache";
/**
* Collection cache configuration properties follow the pattern
* {@code hibernate.collectioncache.packagename.ClassName.role usage[, region]}
* where {@code usage} is the cache strategy used and {@code region} the cache region name
*/
String COLLECTION_CACHE_PREFIX = "hibernate.collectioncache";
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Legacy JPA settings
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* Used to indicate whether second-level (what JPA terms shared cache)
* caching is enabled as per the rules defined in JPA 2 section 3.1.7.
* <p>
* See JPA 2 sections 9.4.3 and 8.2.1.7
* @see jakarta.persistence.SharedCacheMode
*
* @deprecated Use {@link #JAKARTA_SHARED_CACHE_MODE} instead
*/
@Deprecated
@SuppressWarnings("DeprecatedIsStillUsed")
String JPA_SHARED_CACHE_MODE = "javax.persistence.sharedCache.mode";
/**
* @deprecated Use {@link #JAKARTA_SHARED_CACHE_RETRIEVE_MODE} instead
*/
@Deprecated
@SuppressWarnings("DeprecatedIsStillUsed")
String JPA_SHARED_CACHE_RETRIEVE_MODE = "javax.persistence.cache.retrieveMode";
/**
* @deprecated Use {@link #JAKARTA_SHARED_CACHE_STORE_MODE} instead
*/
@Deprecated
@SuppressWarnings("DeprecatedIsStillUsed")
String JPA_SHARED_CACHE_STORE_MODE = "javax.persistence.cache.storeMode";
}

View File

@ -0,0 +1,56 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.cfg;
import java.util.Hashtable;
import javax.naming.InitialContext;
/**
* @author Steve Ebersole
*/
public interface EnvironmentSettings {
/**
* Specifies the JNDI {@link javax.naming.spi.InitialContextFactory} implementation
* class to use. Passed along to {@link InitialContext#InitialContext(Hashtable)}
* as {@value javax.naming.Context#INITIAL_CONTEXT_FACTORY}.
*
* @see javax.naming.Context#INITIAL_CONTEXT_FACTORY
*/
String JNDI_CLASS = "hibernate.jndi.class";
/**
* Specifies the JNDI provider/connection URL. Passed along to
* {@link InitialContext#InitialContext(Hashtable)} as
* {@value javax.naming.Context#PROVIDER_URL}.
*
* @see javax.naming.Context#PROVIDER_URL
*/
String JNDI_URL = "hibernate.jndi.url";
/**
* A prefix for properties specifying arbitrary JNDI {@link javax.naming.InitialContext}
* properties. These properties are simply passed along to the constructor
* {@link javax.naming.InitialContext#InitialContext(java.util.Hashtable)}.
*/
String JNDI_PREFIX = "hibernate.jndi";
/**
* Specifies a {@link java.util.Collection collection} of the {@link ClassLoader}
* instances Hibernate should use for classloading and resource loading.
*
* @since 5.0
*/
String CLASSLOADERS = "hibernate.classLoaders";
/**
* Specifies how the {@linkplain Thread#getContextClassLoader() thread context}
* {@linkplain ClassLoader class loader} must be used for class lookup.
*
* @see org.hibernate.boot.registry.classloading.internal.TcclLookupPrecedence
*/
String TC_CLASSLOADER = "hibernate.classLoader.tccl_lookup_precedence";
}

View File

@ -0,0 +1,62 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.cfg;
import org.hibernate.annotations.BatchSize;
/**
* @author Steve Ebersole
*/
public interface FetchSettings {
/**
* Specifies the maximum depth of nested outer join fetching.
*
* @see org.hibernate.boot.SessionFactoryBuilder#applyMaximumFetchDepth
*
* @settingDefault 0 (none)
*/
String MAX_FETCH_DEPTH = "hibernate.max_fetch_depth";
/**
* Specifies the default value for {@linkplain BatchSize#size() batch fetching}.
* <p/>
* By default, Hibernate only uses batch fetching for entities and collections explicitly
* annotated {@code @BatchSize}.
*
* @see org.hibernate.annotations.BatchSize
* @see org.hibernate.Session#setFetchBatchSize(int)
* @see org.hibernate.boot.SessionFactoryBuilder#applyDefaultBatchFetchSize(int)
*/
String DEFAULT_BATCH_FETCH_SIZE = "hibernate.default_batch_fetch_size";
/**
* When enabled, Hibernate will use subselect fetching, when possible, to
* fetch any collection. Subselect fetching involves fetching the collection
* based on the restriction used to load it owner(s).
* <p>
* By default, Hibernate only uses subselect fetching for collections
* explicitly annotated {@linkplain org.hibernate.annotations.FetchMode#SUBSELECT @Fetch(SUBSELECT)}.
*
* @since 6.3
*
* @see org.hibernate.annotations.FetchMode#SUBSELECT
* @see org.hibernate.Session#setSubselectFetchingEnabled(boolean)
* @see org.hibernate.boot.SessionFactoryBuilder#applySubselectFetchEnabled(boolean)
*/
String USE_SUBSELECT_FETCH = "hibernate.use_subselect_fetch";
/**
* Specifies the {@link org.hibernate.loader.BatchFetchStyle} to use,
* either the name of a {code BatchFetchStyle} instance, or an instance
* of {@code BatchFetchStyle}.
*
* @deprecated An appropriate batch-fetch style is selected automatically
*/
@Deprecated(since = "6.0")
@SuppressWarnings("DeprecatedIsStillUsed")
String BATCH_FETCH_STYLE = "hibernate.batch_fetch_style";
}

View File

@ -0,0 +1,611 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.cfg;
import java.util.Calendar;
import org.hibernate.Incubating;
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData;
import org.hibernate.query.Query;
import org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode;
import org.hibernate.resource.jdbc.spi.StatementInspector;
import org.hibernate.sql.ast.spi.ParameterMarkerStrategy;
/**
* Settings related to JDBC, Connections, pools, Dialects, etc
*
* @author Steve Ebersole
*/
public interface JdbcSettings extends C3p0Settings, ProxoolSettings {
/**
* Specifies a JTA {@link javax.sql.DataSource} to use for Connections.
* Hibernate allows either
* <ul>
* <li>
* an instance of {@link javax.sql.DataSource}
* </li>
* <li>
* a JNDI name under which to obtain the {@link javax.sql.DataSource};
* see also {@link EnvironmentSettings#JNDI_URL}, {@link EnvironmentSettings#JNDI_CLASS},
* {@link EnvironmentSettings#JNDI_PREFIX}
* </li>
* </ul>
* <p>
* See JPA 2 sections 9.4.3 and 8.2.1.5
*/
String JAKARTA_JTA_DATASOURCE = "jakarta.persistence.jtaDataSource";
/**
* Specifies a non-JTA {@link javax.sql.DataSource} to use for Connections.
* Hibernate allows either
* <ul>
* <li>
* an instance of {@link javax.sql.DataSource}
* </li>
* <li>
* a JNDI name under which to obtain the {@link javax.sql.DataSource};
* see also {@link EnvironmentSettings#JNDI_URL}, {@link EnvironmentSettings#JNDI_CLASS},
* {@link EnvironmentSettings#JNDI_PREFIX}
* </li>
* </ul>
* <p>
* See JPA 2 sections 9.4.3 and 8.2.1.5
*/
String JAKARTA_NON_JTA_DATASOURCE = "jakarta.persistence.nonJtaDataSource";
/**
* Specifies the name of a JDBC driver to use to connect to the database.
* <p>
* Used in conjunction with {@link #JAKARTA_JDBC_URL}, {@link #JAKARTA_JDBC_USER}
* and {@link #JAKARTA_JDBC_PASSWORD} to specify how to connect to the database.
* <p>
* When connections are obtained from a {@link javax.sql.DataSource}, use
* either {@link #JAKARTA_JTA_DATASOURCE} or {@link #JAKARTA_NON_JTA_DATASOURCE}
* instead.
* <p>
* See section 8.2.1.9
*/
String JAKARTA_JDBC_DRIVER = "jakarta.persistence.jdbc.driver";
/**
* Specifies the JDBC connection URL to use to connect to the database.
* <p>
* Used in conjunction with {@link #JAKARTA_JDBC_DRIVER}, {@link #JAKARTA_JDBC_USER}
* and {@link #JAKARTA_JDBC_PASSWORD} to specify how to connect to the database.
* <p>
* When connections are obtained from a {@link javax.sql.DataSource}, use
* either {@link #JAKARTA_JTA_DATASOURCE} or {@link #JAKARTA_NON_JTA_DATASOURCE}
* instead.
* <p>
* See section 8.2.1.9
*/
String JAKARTA_JDBC_URL = "jakarta.persistence.jdbc.url";
/**
* Specifies the database user to use when connecting via JDBC.
* <p>
* Used in conjunction with {@link #JAKARTA_JDBC_DRIVER}, {@link #JAKARTA_JDBC_URL}
* and {@link #JAKARTA_JDBC_PASSWORD} to specify how to connect to the database.
* <p>
* Depending on the configured {@link ConnectionProvider}, the specified username might be used to:
* <ul>
* <li>
* create a JDBC connection using
* {@link java.sql.DriverManager#getConnection(String,java.util.Properties)}
* or {@link java.sql.Driver#connect(String,java.util.Properties)}, or
* </li>
* <li>
* obtain a JDBC connection from a datasource, using
* {@link javax.sql.DataSource#getConnection(String, String)}.
* </li>
* </ul>
* <p>
* See section 8.2.1.9
*/
String JAKARTA_JDBC_USER = "jakarta.persistence.jdbc.user";
/**
* Specifies the password to use when connecting via JDBC.
* <p>
* Used in conjunction with {@link #JAKARTA_JDBC_DRIVER}, {@link #JAKARTA_JDBC_URL}
* and {@link #JAKARTA_JDBC_USER} to specify how to connect to the database.
* <p>
* See JPA 2 section 8.2.1.9
*/
String JAKARTA_JDBC_PASSWORD = "jakarta.persistence.jdbc.password";
/**
* Allows passing a specific {@link java.sql.Connection} instance to be used by
* {@link org.hibernate.tool.schema.spi.SchemaManagementTool} for the purpose of
* determining the {@link org.hibernate.dialect.Dialect}, and for performing
* {@link SchemaToolingSettings#JAKARTA_HBM2DDL_DATABASE_ACTION database actions} if requested.
* <p>
* For {@code Dialect} resolution, {@value #JAKARTA_HBM2DDL_DB_NAME} and, optionally,
* {@value JAKARTA_HBM2DDL_DB_VERSION}, {@value #JAKARTA_HBM2DDL_DB_MAJOR_VERSION},
* and {@value #JAKARTA_HBM2DDL_DB_MINOR_VERSION} can be used instead
*
* @see #JAKARTA_HBM2DDL_DB_NAME
* @see #JAKARTA_HBM2DDL_DB_VERSION
* @see #JAKARTA_HBM2DDL_DB_MAJOR_VERSION
* @see #JAKARTA_HBM2DDL_DB_MINOR_VERSION
*/
String JAKARTA_HBM2DDL_CONNECTION = "jakarta.persistence.schema-generation-connection";
/**
* Specifies the name of the database vendor (as would be reported by
* {@link java.sql.DatabaseMetaData#getDatabaseProductName}) for the purpose of
* determining the {@link org.hibernate.dialect.Dialect} to use.
* <p>
* For cases when the name of the database vendor is not enough alone, a combination
* of {@value JAKARTA_HBM2DDL_DB_VERSION}, {@value #JAKARTA_HBM2DDL_DB_MAJOR_VERSION}
* {@value #JAKARTA_HBM2DDL_DB_MINOR_VERSION} can be used instead
*
* @see #JAKARTA_HBM2DDL_DB_VERSION
* @see #JAKARTA_HBM2DDL_DB_MAJOR_VERSION
* @see #JAKARTA_HBM2DDL_DB_MINOR_VERSION
*
* @implSpec {@link SchemaToolingSettings#JAKARTA_HBM2DDL_DATABASE_ACTION database actions} are not
* available when supplying just the name and versions
*/
String JAKARTA_HBM2DDL_DB_NAME = "jakarta.persistence.database-product-name";
/**
* Used in conjunction with {@value #JAKARTA_HBM2DDL_DB_NAME} for the purpose of
* determining the {@link org.hibernate.dialect.Dialect} to use when the name does
* not provide enough detail.
* <p>
* The value is expected to match what would be returned from
* {@link java.sql.DatabaseMetaData#getDatabaseProductVersion()}) for the
* underlying database.
*
* @see #JAKARTA_HBM2DDL_DB_NAME
*/
String JAKARTA_HBM2DDL_DB_VERSION = "jakarta.persistence.database-product-version";
/**
* Used in conjunction with {@value #JAKARTA_HBM2DDL_DB_NAME} for the purpose of
* determining the {@link org.hibernate.dialect.Dialect} to use when the name does
* not provide enough detail.
* <p>
* The value is expected to match what would be returned from
* {@link java.sql.DatabaseMetaData#getDatabaseMajorVersion()}) for the underlying
* database.
*
* @see #JAKARTA_HBM2DDL_DB_NAME
*/
String JAKARTA_HBM2DDL_DB_MAJOR_VERSION = "jakarta.persistence.database-major-version";
/**
* Used in conjunction with {@value #JAKARTA_HBM2DDL_DB_NAME} for the purpose of
* determining the {@link org.hibernate.dialect.Dialect} to use when the name does
* not provide enough detail.
* <p>
* The value is expected to match what would be returned from
* {@link java.sql.DatabaseMetaData#getDatabaseMinorVersion()}) for the underlying
* database.
*
* @see #JAKARTA_HBM2DDL_DB_NAME
*/
String JAKARTA_HBM2DDL_DB_MINOR_VERSION = "jakarta.persistence.database-minor-version";
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Hibernate settings
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* Specifies the Hibernate {@linkplain org.hibernate.dialect.Dialect SQL dialect}, either
* <ul>
* <li>an instance of {@link org.hibernate.dialect.Dialect},
* <li>a {@link Class} representing a class that extends {@code Dialect}, or
* <li>the name of a class that extends {@code Dialect}.
* </ul>
* <p>
* By default, Hibernate will attempt to automatically determine the dialect from the
* {@linkplain #URL JDBC URL} and JDBC metadata, so this setting is not usually necessary.
*
* @apiNote As of Hibernate 6, this property should not be explicitly specified,
* except when using a custom user-written implementation of {@code Dialect}.
* Instead, applications should allow Hibernate to select the {@code Dialect}
* automatically.
*
* @see org.hibernate.dialect.Dialect
*/
String DIALECT = "hibernate.dialect";
/**
* Specifies additional {@link org.hibernate.engine.jdbc.dialect.spi.DialectResolver}
* implementations to register with the standard
* {@link org.hibernate.engine.jdbc.dialect.spi.DialectFactory}.
*/
String DIALECT_RESOLVERS = "hibernate.dialect_resolvers";
/**
* Specifies a {@link ConnectionProvider}
* to use for obtaining JDBC connections, either:
* <ul>
* <li>an instance of {@code ConnectionProvider},
* <li>a {@link Class} representing a class that implements
* {@code ConnectionProvider}, or
* <li>the name of a class that implements {@code ConnectionProvider}.
* </ul>
* <p>
* The term {@code "class"} appears in the setting name due to legacy reasons;
* however it can accept instances.
*/
String CONNECTION_PROVIDER = "hibernate.connection.provider_class";
/**
* Specifies the maximum number of inactive connections for the built-in
* {@linkplain org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl
* connection pool}.
*
* @settingDefault 20
*/
String POOL_SIZE = "hibernate.connection.pool_size";
/**
* Specified the JDBC transaction isolation level.
*/
String ISOLATION = "hibernate.connection.isolation";
/**
* Controls the autocommit mode of JDBC connections obtained from any
* {@link ConnectionProvider} implementation
* which respects this setting, which the built-in implementations do, except for
* {@link org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl}.
*/
String AUTOCOMMIT = "hibernate.connection.autocommit";
/**
* Indicates that Connections obtained from the configured {@link ConnectionProvider} have
* auto-commit already disabled when they are acquired.
* <p>
* It is inappropriate to set this value to {@code true} when the Connections returned by
* the provider do not, in fact, have auto-commit disabled. Doing so may lead to Hibernate
* executing SQL operations outside the scope of any transaction.
*
* @apiNote By default, Hibernate calls {@link java.sql.Connection#setAutoCommit(boolean)} on
* newly-obtained connections. This setting allows to circumvent that call (as well as other
* operations) in the interest of performance.
*
* @settingDefault {@code false}
*
* @see org.hibernate.boot.SessionFactoryBuilder#applyConnectionProviderDisablesAutoCommit(boolean)
*
* @since 5.2.10
*/
String CONNECTION_PROVIDER_DISABLES_AUTOCOMMIT= "hibernate.connection.provider_disables_autocommit";
/**
* A prefix for properties specifying arbitrary JDBC connection properties. These
* properties are simply passed along to the provider when creating a connection.
* <p>
* For example, declaring {@code hibernate.connection.foo=bar} tells Hibernate to
* append {@code foo=bar} to the JDBC connection URL.
*/
String CONNECTION_PREFIX = "hibernate.connection";
/**
* Specifies a {@link org.hibernate.resource.jdbc.spi.StatementInspector}
* implementation associated with the {@link org.hibernate.SessionFactory},
* either:
* <ul>
* <li>an instance of {@code StatementInspector},
* <li>a {@link Class} representing an class that implements {@code StatementInspector}, or
* <li>the name of a class that implements {@code StatementInspector}.
* </ul>
*
* @see org.hibernate.boot.SessionFactoryBuilder#applyStatementInspector(StatementInspector)
*
* @since 5.0
*/
String STATEMENT_INSPECTOR = "hibernate.session_factory.statement_inspector";
/**
* Enables logging of generated SQL to the console.
*
* @settingDefault {@code false}
*/
String SHOW_SQL = "hibernate.show_sql";
/**
* Enables formatting of SQL logged to the console.
*
* @settingDefault {@code false}
*/
String FORMAT_SQL = "hibernate.format_sql";
/**
* Enables highlighting of SQL logged to the console using ANSI escape codes.
*
* @settingDefault {@code false}
*/
String HIGHLIGHT_SQL = "hibernate.highlight_sql";
/**
* Specifies a duration in milliseconds defining the minimum query execution time that
* characterizes a "slow" query. Any SQL query which takes longer than this amount of
* time to execute will be logged.
* <p>
* A value of {@code 0}, the default, disables logging of "slow" queries.
*
* @see org.hibernate.stat.Statistics#getSlowQueries()
*/
String LOG_SLOW_QUERY = "hibernate.log_slow_query";
/**
* Specifies that comments should be added to the generated SQL.
*
* @settingDefault {@code false}
*
* @see org.hibernate.boot.SessionFactoryBuilder#applySqlComments(boolean)
*/
String USE_SQL_COMMENTS = "hibernate.use_sql_comments";
/**
* Gives the JDBC driver a hint as to the number of rows that should be fetched
* from the database when more rows are needed. If {@code 0}, the JDBC driver's
* default settings will be used.
*
* @see java.sql.PreparedStatement#setFetchSize(int)
* @see org.hibernate.boot.SessionFactoryBuilder#applyJdbcFetchSize(int)
* @see org.hibernate.ScrollableResults#setFetchSize(int)
*
* @settingDefault {@code 0}
*/
String STATEMENT_FETCH_SIZE = "hibernate.jdbc.fetch_size";
/**
* Controls how Hibernate should handle scrollable results - <ul>
* <li>
* {@code true} indicates that {@linkplain java.sql.ResultSet#TYPE_SCROLL_INSENSITIVE insensitive} scrolling can be used
* </li>
* <li>
* {@code false} indicates that {@linkplain java.sql.ResultSet#TYPE_SCROLL_SENSITIVE sensitive} scrolling must be used
* </li>
* </ul>
*
* @settingDefault {@code true} if the underlying driver supports scrollable results
*
* @see org.hibernate.boot.SessionFactoryBuilder#applyScrollableResultsSupport(boolean)
* @see Query#scroll
* @see ExtractedDatabaseMetaData#supportsScrollableResults()
*/
String USE_SCROLLABLE_RESULTSET = "hibernate.jdbc.use_scrollable_resultset";
/**
* Controls whether to use JDBC markers (`?`) or dialect native markers for parameters
* within {@linkplain java.sql.PreparedStatement preparable} SQL statements.
*
* @implNote {@code False} by default, indicating standard JDBC parameter markers (`?`)
* are used. Set to {@code true} to use the Dialect's native markers, if any. For
* Dialects without native markers, the standard JDBC strategy is used.
*
* @see ParameterMarkerStrategy
* @see org.hibernate.dialect.Dialect#getNativeParameterMarkerStrategy()
*
* @since 6.2
*/
@Incubating
String DIALECT_NATIVE_PARAM_MARKERS = "hibernate.dialect.native_param_markers";
/**
* When enabled, specifies that Hibernate should not use contextual LOB creation.
*
* @see org.hibernate.engine.jdbc.LobCreator
* @see org.hibernate.engine.jdbc.LobCreationContext
*/
String NON_CONTEXTUAL_LOB_CREATION = "hibernate.jdbc.lob.non_contextual_creation";
/**
* When enabled, specifies that JDBC statement warnings should be logged.
* <p>
* The default is determined by
* {@link org.hibernate.dialect.Dialect#isJdbcLogWarningsEnabledByDefault()}.
*
* @see java.sql.Statement#getWarnings()
*
* @since 5.1
*/
String LOG_JDBC_WARNINGS = "hibernate.jdbc.log.warnings";
/**
* Specifies the {@linkplain java.util.TimeZone time zone} to use in the JDBC driver,
* which is supposed to match the database timezone.
* <p>
* This is the timezone what will be passed to
* {@link java.sql.PreparedStatement#setTimestamp(int, java.sql.Timestamp, java.util.Calendar)}
* {@link java.sql.PreparedStatement#setTime(int, java.sql.Time, java.util.Calendar)},
* {@link java.sql.ResultSet#getTimestamp(int, Calendar)}, and
* {@link java.sql.ResultSet#getTime(int, Calendar)} when binding parameters.
* <p>
* The time zone may be given as:
* <ul>
* <li>an instance of {@link java.util.TimeZone},
* <li>an instance of {@link java.time.ZoneId}, or
* <li>a time zone ID string to be passed to {@link java.time.ZoneId#of(String)}.
* </ul>
* <p>
* By default, the {@linkplain java.util.TimeZone#getDefault() JVM default time zone}
* is assumed by the JDBC driver.
*
* @since 5.2.3
*/
String JDBC_TIME_ZONE = "hibernate.jdbc.time_zone";
/**
* Specifies that generated primary keys may be retrieved using the JDBC 3
* {@link java.sql.PreparedStatement#getGeneratedKeys()} operation.
* <p>
* Usually, performance will be improved if this behavior is enabled, assuming
* the JDBC driver supports {@code getGeneratedKeys()}.
*
* @see java.sql.PreparedStatement#getGeneratedKeys
* @see org.hibernate.boot.SessionFactoryBuilder#applyGetGeneratedKeysSupport(boolean)
*/
String USE_GET_GENERATED_KEYS = "hibernate.jdbc.use_get_generated_keys";
/**
* Specifies how Hibernate should manage JDBC connections in terms of acquisition
* and release, either:
* <ul>
* <li>an instance of the enumeration
* {@link org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode},
* or
* <li>the name of one of its instances.
* </ul>
* <p>
* The default is {@code DELAYED_ACQUISITION_AND_RELEASE_AFTER_TRANSACTION}.
*
* @see org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode
* @see org.hibernate.boot.SessionFactoryBuilder#applyConnectionHandlingMode(PhysicalConnectionHandlingMode)
*
* @since 5.2
*/
String CONNECTION_HANDLING = "hibernate.connection.handling_mode";
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Deprecated Hibernate settings
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* @deprecated The JPA-standard setting {@link #JAKARTA_JDBC_DRIVER} is now preferred.
*/
@Deprecated
String DRIVER = "hibernate.connection.driver_class";
/**
* @deprecated The JPA-standard setting {@link #JAKARTA_JDBC_URL} is now preferred.
*/
@Deprecated
String URL = "hibernate.connection.url";
/**
* @see #PASS
*
* @deprecated The JPA-standard setting {@link #JAKARTA_JDBC_USER} is now preferred.
*/
@Deprecated
String USER = "hibernate.connection.username";
/**
* @see #USER
*
* @deprecated The JPA-standard setting {@link #JAKARTA_JDBC_USER} is now preferred.
*/
@Deprecated
String PASS = "hibernate.connection.password";
/**
* @see javax.sql.DataSource
*
* @deprecated The JPA-standard {@link #JAKARTA_JTA_DATASOURCE} or {@link #JAKARTA_JTA_DATASOURCE} setting
* is now preferred.
*/
@Deprecated
String DATASOURCE = "hibernate.connection.datasource";
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Legacy JPA settings
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* @deprecated Use {@link #JAKARTA_JTA_DATASOURCE} instead
*/
@Deprecated
@SuppressWarnings("DeprecatedIsStillUsed")
String JPA_JTA_DATASOURCE = "javax.persistence.jtaDataSource";
/**
* @deprecated Use {@link #JAKARTA_NON_JTA_DATASOURCE} instead
*/
@Deprecated
@SuppressWarnings("DeprecatedIsStillUsed")
String JPA_NON_JTA_DATASOURCE = "javax.persistence.nonJtaDataSource";
/**
* @deprecated Use {@link #JAKARTA_JDBC_DRIVER} instead
*/
@Deprecated
@SuppressWarnings("DeprecatedIsStillUsed")
String JPA_JDBC_DRIVER = "javax.persistence.jdbc.driver";
/**
* @deprecated Use {@link #JAKARTA_JDBC_URL} instead
*/
@Deprecated
@SuppressWarnings("DeprecatedIsStillUsed")
String JPA_JDBC_URL = "javax.persistence.jdbc.url";
/**
* @deprecated Use {@link #JAKARTA_JDBC_USER} instead
*/
@Deprecated
@SuppressWarnings("DeprecatedIsStillUsed")
String JPA_JDBC_USER = "javax.persistence.jdbc.user";
/**
* @deprecated Use {@link #JAKARTA_JDBC_PASSWORD} instead
*/
@Deprecated
@SuppressWarnings("DeprecatedIsStillUsed")
String JPA_JDBC_PASSWORD = "javax.persistence.jdbc.password";
/**
* @deprecated Use {@link #JAKARTA_HBM2DDL_CONNECTION} instead
*/
@Deprecated
@SuppressWarnings("DeprecatedIsStillUsed")
String HBM2DDL_CONNECTION = "javax.persistence.schema-generation-connection";
/**
* @see #DIALECT_DB_VERSION
* @see #DIALECT_DB_MAJOR_VERSION
* @see #DIALECT_DB_MINOR_VERSION
*
* @deprecated Use {@link #JAKARTA_HBM2DDL_DB_NAME} instead
*/
@Deprecated
@SuppressWarnings("DeprecatedIsStillUsed")
String DIALECT_DB_NAME = "javax.persistence.database-product-name";
/**
* @see #DIALECT_DB_NAME
*
* @deprecated Use {@link #JAKARTA_HBM2DDL_DB_VERSION} instead
*/
@Deprecated
@SuppressWarnings("DeprecatedIsStillUsed")
String DIALECT_DB_VERSION = "javax.persistence.database-product-version";
/**
* @see #DIALECT_DB_NAME
* @see #DIALECT_DB_MINOR_VERSION
*
* @deprecated Use {@link #JAKARTA_HBM2DDL_DB_MAJOR_VERSION} instead
*/
@Deprecated
@SuppressWarnings("DeprecatedIsStillUsed")
String DIALECT_DB_MAJOR_VERSION = "javax.persistence.database-major-version";
/**
* @see #DIALECT_DB_NAME
* @see #DIALECT_DB_MAJOR_VERSION
* @see org.hibernate.engine.jdbc.dialect.spi.DialectResolver
*
* @deprecated Use {@link #JAKARTA_HBM2DDL_DB_MINOR_VERSION} instead
*/
@Deprecated
@SuppressWarnings("DeprecatedIsStillUsed")
String DIALECT_DB_MINOR_VERSION = "javax.persistence.database-minor-version";
}

View File

@ -0,0 +1,217 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.cfg;
/**
* @author Steve Ebersole
*/
public interface JpaComplianceSettings {
/**
* Specifies a default value for all {@link org.hibernate.jpa.spi.JpaCompliance}
* flags. Each individual flag may still be overridden by explicitly specifying
* its specific configuration property.
*
* @settingDefault {@code true} with JPA bootstrapping; {@code false} otherwise.
*
* @see #JPA_TRANSACTION_COMPLIANCE
* @see #JPA_QUERY_COMPLIANCE
* @see #JPA_LIST_COMPLIANCE
* @see #JPA_ORDER_BY_MAPPING_COMPLIANCE
* @see #JPA_CLOSED_COMPLIANCE
* @see #JPA_PROXY_COMPLIANCE
* @see #JPA_CACHING_COMPLIANCE
* @see #JPA_ID_GENERATOR_GLOBAL_SCOPE_COMPLIANCE
* @see #JPA_LOAD_BY_ID_COMPLIANCE
*
* @since 6.0
*/
String JPA_COMPLIANCE = "hibernate.jpa.compliance";
/**
* When enabled, specifies that the Hibernate {@link org.hibernate.Transaction}
* should behave according to the semantics defined by the JPA specification for
* an {@link jakarta.persistence.EntityTransaction}.
*
* @settingDefault {@link #JPA_COMPLIANCE}
*
* @see org.hibernate.jpa.spi.JpaCompliance#isJpaTransactionComplianceEnabled()
* @see org.hibernate.boot.SessionFactoryBuilder#enableJpaTransactionCompliance(boolean)
*
* @since 5.3
*/
String JPA_TRANSACTION_COMPLIANCE = "hibernate.jpa.compliance.transaction";
/**
* Controls whether Hibernates handling of {@link jakarta.persistence.Query}
* (JPQL, Criteria and native) should strictly follow the requirements defined
* in the Jakarta Persistence specification, both in terms of JPQL validation
* and behavior of {@link jakarta.persistence.Query} method implementations.
*
* @settingDefault {@link #JPA_COMPLIANCE}
*
* @apiNote When disabled, allows the many useful features of HQL
*
* @see org.hibernate.jpa.spi.JpaCompliance#isJpaQueryComplianceEnabled()
* @see org.hibernate.boot.SessionFactoryBuilder#enableJpaQueryCompliance(boolean)
*
* @since 5.3
*/
String JPA_QUERY_COMPLIANCE = "hibernate.jpa.compliance.query";
/**
* Controls whether Hibernate should treat what it would usually consider a
* {@linkplain org.hibernate.collection.spi.PersistentBag "bag"}, that is, a
* list with no index column, whose element order is not persistent, as a true
* {@link org.hibernate.collection.spi.PersistentList list} with an index column
* and a persistent element order.
*
* @apiNote If enabled, Hibernate will recognize it as a list where the
* {@link jakarta.persistence.OrderColumn} annotation is simply missing
* (and its defaults will apply).
*
* @settingDefault {@link #JPA_COMPLIANCE}
*
* @see org.hibernate.jpa.spi.JpaCompliance#isJpaListComplianceEnabled()
* @see org.hibernate.boot.SessionFactoryBuilder#enableJpaListCompliance(boolean)
*
* @since 5.3
*
* @deprecated Use {@link MappingSettings#DEFAULT_LIST_SEMANTICS} instead. The specification
* actually leaves this behavior undefined, saying that portable applications
* should not rely on any specific behavior for a {@link java.util.List} with
* no {@code @OrderColumn}.
*/
@Deprecated( since = "6.0" )
@SuppressWarnings("DeprecatedIsStillUsed")
String JPA_LIST_COMPLIANCE = "hibernate.jpa.compliance.list";
/**
* JPA specifies that items occurring in {@link jakarta.persistence.OrderBy}
* lists must be references to entity attributes, whereas Hibernate, by default,
* allows more complex expressions.
*
* @apiNote If enabled, an exception is thrown for items which are not entity attribute
* references.
*
* @settingDefault {@link #JPA_COMPLIANCE}
*
* @see org.hibernate.jpa.spi.JpaCompliance#isJpaOrderByMappingComplianceEnabled()
* @see org.hibernate.boot.SessionFactoryBuilder#enableJpaOrderByMappingCompliance(boolean)
*
* @since 6.0
*/
String JPA_ORDER_BY_MAPPING_COMPLIANCE = "hibernate.jpa.compliance.orderby";
/**
* JPA specifies that an {@link IllegalStateException} must be thrown by
* {@link jakarta.persistence.EntityManager#close()} and
* {@link jakarta.persistence.EntityManagerFactory#close()} if the object has
* already been closed. By default, Hibernate treats any additional call to
* {@code close()} as a noop.
*
* @apiNote When enabled, this setting forces Hibernate to throw an exception if
* {@code close()} is called on an instance that was already closed.
*
* @settingDefault {@link #JPA_COMPLIANCE}
*
* @see org.hibernate.jpa.spi.JpaCompliance#isJpaClosedComplianceEnabled()
* @see org.hibernate.boot.SessionFactoryBuilder#enableJpaClosedCompliance(boolean)
*
* @since 5.3
*/
String JPA_CLOSED_COMPLIANCE = "hibernate.jpa.compliance.closed";
/**
* The JPA specification insists that an
* {@link jakarta.persistence.EntityNotFoundException} must be thrown whenever
* an uninitialized entity proxy with no corresponding row in the database is
* accessed. For most programs, this results in many completely unnecessary
* round trips to the database.
* <p>
* Traditionally, Hibernate does not initialize an entity proxy when its
* identifier attribute is accessed, since the identifier value is already
* known and held in the proxy instance. This behavior saves the round trip
* to the database.
*
* @apiNote When enabled, this setting forces Hibernate to initialize the entity proxy
* when its identifier is accessed. Clearly, this setting is not recommended.
*
* @settingDefault {@link #JPA_COMPLIANCE}
*
* @see org.hibernate.jpa.spi.JpaCompliance#isJpaProxyComplianceEnabled()
*
* @since 5.2.13
*/
String JPA_PROXY_COMPLIANCE = "hibernate.jpa.compliance.proxy";
/**
* By default, Hibernate uses second-level cache invalidation for entities
* with {@linkplain jakarta.persistence.SecondaryTable secondary tables}
* in order to avoid the possibility of inconsistent cached data in the
* case where different transactions simultaneously update different table
* rows corresponding to the same entity instance.
* <p>
* The Jakarta Persistence TCK, requires that entities with secondary
* tables be immediately cached in the second-level cache rather than
* invalidated and re-cached on a subsequent read.
*
* @settingDefault {@link #JPA_COMPLIANCE}
*
* @apiNote Hibernate's default behavior here is safer and more careful
* than the behavior mandated by the TCK but YOLO
*
* @see org.hibernate.jpa.spi.JpaCompliance#isJpaCacheComplianceEnabled()
* @see org.hibernate.persister.entity.AbstractEntityPersister#isCacheInvalidationRequired()
*
* @since 5.3
*/
String JPA_CACHING_COMPLIANCE = "hibernate.jpa.compliance.caching";
/**
* Determines whether the scope of any identifier generator name specified
* via {@link jakarta.persistence.TableGenerator#name()} or
* {@link jakarta.persistence.SequenceGenerator#name()} is considered global
* to the persistence unit, or local to the entity in which identifier generator
* is defined.
*
* @apiNote If enabled, the name will be considered globally scoped, and so the existence
* of two different generators with the same name will be considered a collision,
* and will result in an exception during bootstrap.
*
* @settingDefault {@link #JPA_COMPLIANCE}
*
* @see org.hibernate.jpa.spi.JpaCompliance#isGlobalGeneratorScopeEnabled()
*
* @since 5.2.17
*/
String JPA_ID_GENERATOR_GLOBAL_SCOPE_COMPLIANCE = "hibernate.jpa.compliance.global_id_generators";
/**
* Determines if an identifier value passed to
* {@link jakarta.persistence.EntityManager#find} or
* {@link jakarta.persistence.EntityManager#getReference} may be
* {@linkplain org.hibernate.type.descriptor.java.JavaType#coerce coerced} to
* the identifier type declared by the entity. For example, an {@link Integer}
* argument might be widened to {@link Long}.
*
* @settingDefault {@link #JPA_COMPLIANCE}
*
* @apiNote When enabled, coercion is disallowed, as required by the JPA specification.
* Hibernate's default (here non-compliant) behavior is to allow the coercion.
*
* @see org.hibernate.jpa.spi.JpaCompliance#isLoadByIdComplianceEnabled()
*
* @since 6.0
*/
String JPA_LOAD_BY_ID_COMPLIANCE = "hibernate.jpa.compliance.load_by_id";
/**
* @deprecated Prefer {@link #JPA_QUERY_COMPLIANCE}
*/
@Deprecated
String JPAQL_STRICT_COMPLIANCE= "hibernate.query.jpaql_strict_compliance";
}

View File

@ -0,0 +1,105 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.cfg;
/**
* @author Steve Ebersole
*/
public interface ManagedBeanSettings {
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// JPA settings
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* Used to pass a CDI {@link jakarta.enterprise.inject.spi.BeanManager} to
* Hibernate.
* <p>
* According to the JPA specification, the {@code BeanManager} should be
* passed at boot time and be ready for immediate use at that time. But
* not all environments can do this (WildFly, for example). To accommodate
* such environments, Hibernate provides two options: <ol>
* <li> A proprietary CDI extension SPI (which has been proposed to the CDI
* spec group as a standard option) which can be used to provide delayed
* {@code BeanManager} access: to use this solution, the reference passed
* as the {@code BeanManager} during bootstrap should be typed as
* {@link org.hibernate.resource.beans.container.spi.ExtendedBeanManager}.
* <li> Delayed access to the {@code BeanManager} reference: here, Hibernate
* will not access the reference passed as the {@code BeanManager} during
* bootstrap until it is first needed. Note, however, that this has the
* effect of delaying the detection of any deployment problems until after
* bootstrapping.
* </ol>
*
* This setting is used to configure access to the {@code BeanManager},
* either directly, or via
* {@link org.hibernate.resource.beans.container.spi.ExtendedBeanManager}.
*
* @see org.hibernate.boot.SessionFactoryBuilder#applyBeanManager(Object)
*/
String JAKARTA_CDI_BEAN_MANAGER = "jakarta.persistence.bean.manager";
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Hibernate settings
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* Identifies a {@link org.hibernate.resource.beans.container.spi.BeanContainer}
* to be used.
* <p>
* Note that for CDI-based containers setting this is not necessary - simply
* pass the {@link jakarta.enterprise.inject.spi.BeanManager} to use via
* {@link #CDI_BEAN_MANAGER} and optionally specify {@link #DELAY_CDI_ACCESS}.
* This setting useful to integrate non-CDI bean containers such as Spring.
*
* @since 5.3
*/
String BEAN_CONTAINER = "hibernate.resource.beans.container";
/**
* Used in conjunction with {@value #BEAN_CONTAINER} when CDI is used.
* <p>
* By default, to be JPA spec compliant, Hibernate should access the CDI
* {@link jakarta.enterprise.inject.spi.BeanManager} while bootstrapping the
* {@link org.hibernate.SessionFactory}. In some cases however this can lead
* to a chicken/egg situation where the JPA provider immediately accesses the
* {@code BeanManager} when managed beans are awaiting JPA PU injection.
* <p>
* This setting tells Hibernate to delay accessing until first use.
* <p>
* This setting has the decided downside that bean config problems will not
* be done at deployment time, but will instead manifest at runtime. For this
* reason, the preferred means for supplying a CDI BeanManager is to provide
* an implementation of
* {@link org.hibernate.resource.beans.container.spi.ExtendedBeanManager} which
* gives Hibernate a callback when the {@code BeanManager} is ready for use.
*
* @since 5.0.8
*/
String DELAY_CDI_ACCESS = "hibernate.delay_cdi_access";
/**
* Controls whether Hibernate can try to create beans other than converters
* and listeners using CDI. Only meaningful when a CDI {@link #BEAN_CONTAINER container}
* is used.
* <p>
* By default, Hibernate will only attempt to create converter and listener beans using CDI.
*
* @since 6.2
*/
String ALLOW_EXTENSIONS_IN_CDI = "hibernate.cdi.extensions";
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Legacy JPA setting
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* @deprecated Use {@link #JAKARTA_CDI_BEAN_MANAGER} instead
*/
@Deprecated
String CDI_BEAN_MANAGER = "javax.persistence.bean.manager";
}

View File

@ -0,0 +1,572 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.cfg;
import org.hibernate.Incubating;
import org.hibernate.Remove;
import org.hibernate.SessionFactory;
import org.hibernate.annotations.ListIndexBase;
import org.hibernate.annotations.Nationalized;
import org.hibernate.boot.jaxb.hbm.transform.UnsupportedFeatureHandling;
import org.hibernate.boot.registry.selector.spi.StrategySelector;
import org.hibernate.dialect.Dialect;
import org.hibernate.id.enhanced.ImplicitDatabaseObjectNamingStrategy;
import org.hibernate.id.enhanced.StandardOptimizerDescriptor;
import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.type.WrapperArrayHandling;
import org.hibernate.type.format.FormatMapper;
import jakarta.persistence.Column;
import jakarta.persistence.DiscriminatorColumn;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.OrderColumn;
/**
* @author Steve Ebersole
*/
public interface MappingSettings {
/**
* A default database catalog name to use for unqualified database
* object (table, sequence, ...) names
*
* @see org.hibernate.boot.MetadataBuilder#applyImplicitCatalogName
*/
String DEFAULT_CATALOG = "hibernate.default_catalog";
/**
* A default database schema (owner) name to use for unqualified
* database object (table, sequence, ...) names
*
* @see org.hibernate.boot.MetadataBuilder#applyImplicitSchemaName
*/
String DEFAULT_SCHEMA = "hibernate.default_schema";
/**
* Setting that indicates whether to build the JPA types, either:<ul>
* <li>
* <b>enabled</b> - Do the build
* </li>
* <li>
* <b>disabled</b> - Do not do the build
* </li>
* <li>
* <b>ignoreUnsupported</b> - Do the build, but ignore any non-JPA
* features that would otherwise result in a failure.
* </li>
* </ul>
*/
String JPA_METAMODEL_POPULATION = "hibernate.jpa.metamodel.population";
/**
* Setting that controls whether we seek out JPA "static metamodel" classes
* and populate them, either:<ul>
* <li>
* <b>enabled</b> - Do the population
* </li>
* <li>
* <b>disabled</b> - Do not do the population
* </li>
* <li>
* <b>skipUnsupported</b> - Do the population, but ignore any non-JPA
* features that would otherwise result in the population failing.
* </li>
* </ul>
*/
String STATIC_METAMODEL_POPULATION = "hibernate.jpa.static_metamodel.population";
/**
* When enabled, all database identifiers are quoted.
* <p>
* Corollary to the JPA {@code <delimited-identifiers/>} element within
* the {@code orm.xml} {@code <persistence-unit-defaults/>} element, but
* offered as a global flag.
*
* @settingDefault {@code false}
*/
String GLOBALLY_QUOTED_IDENTIFIERS = "hibernate.globally_quoted_identifiers";
/**
* Controls whether column-definitions ({@link Column#columnDefinition},
* {@link JoinColumn#columnDefinition}, etc.) should be auto-quoted as part of
* {@linkplain #GLOBALLY_QUOTED_IDENTIFIERS global quoting}.
* <p>
* When {@linkplain #GLOBALLY_QUOTED_IDENTIFIERS global quoting} is enabled, JPA
* <a href="https://jakarta.ee/specifications/persistence/3.1/jakarta-persistence-spec-3.1.html#a988">states</a>
* that column-definitions are subject to quoting. However, this can lead to problems
* with definitions such as {@code @Column(..., columnDefinition="INTEGER DEFAULT 20")}.
*
* @settingDefault {@code false} to avoid the potential problems quoting non-trivial
* column-definitions.
*/
String GLOBALLY_QUOTED_IDENTIFIERS_SKIP_COLUMN_DEFINITIONS = "hibernate.globally_quoted_identifiers_skip_column_definitions";
/**
* Specifies whether to automatically quote any names that are deemed keywords
* on the underlying database.
*
* @settingDefault {@code false} - auto-quoting of SQL keywords is disabled by default.
*
* @since 5.0
*/
String KEYWORD_AUTO_QUOTING_ENABLED = "hibernate.auto_quote_keyword";
/**
* When a generator specifies an increment-size and an optimizer was not explicitly
* specified, which of the "pooled" optimizers should be preferred? Can specify an
* optimizer short name or the name of a class which implements
* {@link org.hibernate.id.enhanced.Optimizer}.
*
* @settingDefault {@link StandardOptimizerDescriptor#POOLED}
*/
String PREFERRED_POOLED_OPTIMIZER = "hibernate.id.optimizer.pooled.preferred";
/**
* Determines if the identifier value stored in the database table backing a
* {@linkplain jakarta.persistence.TableGenerator table generator} is the last
* value returned by the identifier generator, or the next value to be returned.
*
* @settingDefault The value stored in the database table is the last generated value
*
* @since 5.3
*/
String TABLE_GENERATOR_STORE_LAST_USED = "hibernate.id.generator.stored_last_used";
/**
* This setting defines the {@link org.hibernate.id.SequenceMismatchStrategy} used
* when Hibernate detects a mismatch between a sequence configuration in an entity
* mapping and its database sequence object counterpart.
* <p>
* Possible values are {@link org.hibernate.id.SequenceMismatchStrategy#EXCEPTION},
* {@link org.hibernate.id.SequenceMismatchStrategy#LOG},
* {@link org.hibernate.id.SequenceMismatchStrategy#FIX}
* and {@link org.hibernate.id.SequenceMismatchStrategy#NONE}.
*
* @settingDefault {@link org.hibernate.id.SequenceMismatchStrategy#EXCEPTION}, meaning
* that an exception is thrown when such a conflict is detected.
*
* @since 5.4
*/
String SEQUENCE_INCREMENT_SIZE_MISMATCH_STRATEGY = "hibernate.id.sequence.increment_size_mismatch_strategy";
/**
* Specifies the preferred JDBC type for storing boolean values.
* <p>
* Can be overridden locally using {@link org.hibernate.annotations.JdbcType},
* {@link org.hibernate.annotations.JdbcTypeCode}, and friends.
* <p>
* Can also specify the name of the {@link org.hibernate.type.SqlTypes} constant
* field, for example, {@code hibernate.type.preferred_boolean_jdbc_type=BIT}.
*
* @settingDefault {@linkplain Dialect#getPreferredSqlTypeCodeForBoolean dialect-specific type code}
*
* @since 6.0
*/
@Incubating
String PREFERRED_BOOLEAN_JDBC_TYPE = "hibernate.type.preferred_boolean_jdbc_type";
/**
* The preferred JDBC type to use for storing {@link java.util.UUID} values.
* <p>
* Can be overridden locally using {@link org.hibernate.annotations.JdbcType},
* {@link org.hibernate.annotations.JdbcTypeCode}, and friends.
* <p>
* Can also specify the name of the {@link org.hibernate.type.SqlTypes} constant
* field, for example, {@code hibernate.type.preferred_uuid_jdbc_type=CHAR}.
*
* @settingDefault {@link org.hibernate.type.SqlTypes#UUID}.
*
* @since 6.0
*/
@Incubating
String PREFERRED_UUID_JDBC_TYPE = "hibernate.type.preferred_uuid_jdbc_type";
/**
* The preferred JDBC type to use for storing {@link java.time.Duration} values.
* <p>
* Can be overridden locally using {@link org.hibernate.annotations.JdbcType},
* {@link org.hibernate.annotations.JdbcTypeCode}, and friends.
* <p>
* Can also specify the name of the {@link org.hibernate.type.SqlTypes} constant
* field, for example, {@code hibernate.type.preferred_duration_jdbc_type=INTERVAL_SECOND}.
*
* @settingDefault {@link org.hibernate.type.SqlTypes#NUMERIC}
*
* @since 6.0
*/
@Incubating
String PREFERRED_DURATION_JDBC_TYPE = "hibernate.type.preferred_duration_jdbc_type";
/**
* Specifies the preferred JDBC type for storing {@link java.time.Instant} values.
* <p>
* Can be overridden locally using {@link org.hibernate.annotations.JdbcType},
* {@link org.hibernate.annotations.JdbcTypeCode}, and friends.
* <p>
* Can also specify the name of the {@link org.hibernate.type.SqlTypes} constant
* field, for example, {@code hibernate.type.preferred_instant_jdbc_type=TIMESTAMP}.
*
* @settingDefault {@link org.hibernate.type.SqlTypes#TIMESTAMP_UTC}.
*
* @since 6.0
*/
@Incubating
String PREFERRED_INSTANT_JDBC_TYPE = "hibernate.type.preferred_instant_jdbc_type";
/**
* Specifies a {@link org.hibernate.type.format.FormatMapper} used for JSON
* serialization and deserialization, either:
* <ul>
* <li>an instance of {@code FormatMapper},
* <li>a {@link Class} representing a class that implements {@code FormatMapper},
* <li>the name of a class that implements {@code FormatMapper}, or
* <li>one of the shorthand constants {@code jackson} or {@code jsonb}.
* </ul>
* <p>
* By default, the first of the possible providers that is available at runtime is
* used, according to the listing order.
*
* @since 6.0
* @see org.hibernate.boot.SessionFactoryBuilder#applyJsonFormatMapper(FormatMapper)
*/
@Incubating
String JSON_FORMAT_MAPPER = "hibernate.type.json_format_mapper";
/**
* Specifies a {@link org.hibernate.type.format.FormatMapper} used for XML
* serialization and deserialization, either:
* <ul>
* <li>an instance of {@code FormatMapper},
* <li>a {@link Class} representing a class that implements {@code FormatMapper},
* <li>the name of a class that implements {@code FormatMapper}, or
* <li>one of the shorthand constants {@code jackson} or {@code jaxb}.
* </ul>
* <p>
* By default, the first of the possible providers that is available at runtime is
* used, according to the listing order.
*
* @since 6.0.1
* @see org.hibernate.boot.SessionFactoryBuilder#applyXmlFormatMapper(FormatMapper)
*/
@Incubating
String XML_FORMAT_MAPPER = "hibernate.type.xml_format_mapper";
/**
* Configurable control over how to handle {@code Byte[]} and {@code Character[]} types
* encountered in the application domain model. Allowable semantics are defined by
* {@link WrapperArrayHandling}. Accepted values include:<ol>
* <li>{@link WrapperArrayHandling} instance</li>
* <li>case-insensitive name of a {@link WrapperArrayHandling} instance (e.g. {@code allow})</li>
* </ol>
*
* @since 6.2
*/
@Incubating
String WRAPPER_ARRAY_HANDLING = "hibernate.type.wrapper_array_handling";
/**
* Specifies the default strategy for storage of the timezone information for the zoned
* datetime types {@link java.time.OffsetDateTime} and {@link java.time.ZonedDateTime}.
* The possible options for this setting are enumerated by
* {@link org.hibernate.annotations.TimeZoneStorageType}.
*
* @apiNote For backward compatibility with older versions of Hibernate, set this property to
* {@link org.hibernate.annotations.TimeZoneStorageType#NORMALIZE NORMALIZE}.
*
* @settingDefault {@link org.hibernate.annotations.TimeZoneStorageType#DEFAULT DEFAULT},
* which guarantees that the {@linkplain java.time.OffsetDateTime#toInstant() instant}
* represented by a zoned datetime type is preserved by a round trip to the database.
* It does <em>not</em> guarantee that the time zone or offset is preserved.
*
* @see org.hibernate.annotations.TimeZoneStorageType
* @see org.hibernate.annotations.TimeZoneStorage
*
* @since 6.0
*/
String TIMEZONE_DEFAULT_STORAGE = "hibernate.timezone.default_storage";
/**
* Used to specify the {@link org.hibernate.boot.model.naming.ImplicitNamingStrategy}
* class to use. The following shortcut names are defined for this setting:
* <ul>
* <li>{@code "default"} and {@code "jpa"} are an abbreviations for
* {@link org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl}
* <li>{@code "legacy-jpa"} is an abbreviation for
* {@link org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl}
* <li>{@code "legacy-hbm"} is an abbreviation for
* {@link org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyHbmImpl}
* <li>{@code "component-path"} is an abbreviation for
* {@link org.hibernate.boot.model.naming.ImplicitNamingStrategyComponentPathImpl}
* </ul>
*
* @settingDefault {@code "default"}
*
* @see org.hibernate.boot.MetadataBuilder#applyImplicitNamingStrategy
*
* @since 5.0
*/
String IMPLICIT_NAMING_STRATEGY = "hibernate.implicit_naming_strategy";
/**
* Specifies the {@link org.hibernate.boot.model.naming.PhysicalNamingStrategy} to use.
*
* @settingDefault {@link org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl},
* in which case physical names are taken to be identical to logical names.
*
* @see org.hibernate.boot.MetadataBuilder#applyPhysicalNamingStrategy
*
* @since 5.0
*/
String PHYSICAL_NAMING_STRATEGY = "hibernate.physical_naming_strategy";
/**
* An implicit naming strategy for database structures (tables, sequences) related
* to identifier generators.
* <p>
* Resolution uses the {@link org.hibernate.boot.registry.selector.spi.StrategySelector}
* service and accepts any of the forms discussed on
* {@link StrategySelector#resolveDefaultableStrategy(Class, Object, java.util.concurrent.Callable)}.
* <p>
* The recognized short names being:<ul>
* <li>{@value org.hibernate.id.enhanced.SingleNamingStrategy#STRATEGY_NAME}</li>
* <li>{@value org.hibernate.id.enhanced.LegacyNamingStrategy#STRATEGY_NAME}</li>
* <li>{@value org.hibernate.id.enhanced.StandardNamingStrategy#STRATEGY_NAME}</li>
* </ul>
*
* @settingDefault {@link org.hibernate.id.enhanced.StandardNamingStrategy}
*
* @since 6
*
* @see ImplicitDatabaseObjectNamingStrategy
*/
@Incubating
String ID_DB_STRUCTURE_NAMING_STRATEGY = "hibernate.id.db_structure_naming_strategy";
/**
* Used to specify the {@link org.hibernate.boot.model.relational.ColumnOrderingStrategy}
* class to use. The following shortcut names are defined for this setting:
* <ul>
* <li>{@code "default"} is an abbreviations for
* {@link org.hibernate.boot.model.relational.ColumnOrderingStrategyStandard}
* <li>{@code "legacy"} is an abbreviation for
* {@link org.hibernate.boot.model.relational.ColumnOrderingStrategyLegacy}
* </ul>
*
* @settingDefault {@code "default"}
*
* @see org.hibernate.boot.MetadataBuilder#applyColumnOrderingStrategy
*
* @since 6.2
*/
String COLUMN_ORDERING_STRATEGY = "hibernate.column_ordering_strategy";
/**
* Specifies the order in which metadata sources should be processed, is a delimited list
* of values defined by {@link MetadataSourceType}.
*
* @settingDefault {@code "hbm,class"}, which indicates that {@code hbm.xml} files
* should be processed first, followed by annotations and {@code orm.xml} files.
*
* @see MetadataSourceType
* @see org.hibernate.boot.MetadataBuilder#applySourceProcessOrdering(MetadataSourceType...)
*
* @deprecated {@code hbm.xml} mappings are no longer supported, making this attribute irrelevant
*/
@SuppressWarnings("DeprecatedIsStillUsed")
@Deprecated(since = "6", forRemoval = true)
String ARTIFACT_PROCESSING_ORDER = "hibernate.mapping.precedence";
/**
* Whether XML mappings should be processed.
*
* @apiNote This is a performance optimization appropriate when mapping details
* are defined exclusively using annotations.
*
* @settingDefault {@code true} - XML mappings are processed
*
* @since 5.4.1
*/
String XML_MAPPING_ENABLED = "hibernate.xml_mapping_enabled";
/**
* Specifies the {@link CollectionClassification} to use for a plural attribute
* typed as {@link java.util.List} with no explicit list index details
* ({@link OrderColumn}, {@link ListIndexBase}, etc.).
* <p>
* Accepts any of:
* <ul>
* <li>an instance of {@code CollectionClassification}
* <li>the (case insensitive) name of a {@code CollectionClassification} (list e.g.)
* <li>a {@link Class} representing either {@link java.util.List} or {@link java.util.Collection}
* </ul>
*
* @settingDefault {@link CollectionClassification#BAG}
*
* @since 6.0
*
* @see org.hibernate.annotations.Bag
*/
String DEFAULT_LIST_SEMANTICS = "hibernate.mapping.default_list_semantics";
/**
* Enable instantiation of composite/embedded objects when all attribute values
* are {@code null}. The default (and historical) behavior is that a {@code null}
* reference will be used to represent the composite value when all of its
* attributes are {@code null}.
*
* @apiNote This is an experimental feature that has known issues. It should not
* be used in production until it is stabilized. See Hibernate JIRA issue
* HHH-11936 for details.
*
* @deprecated It makes no sense at all to enable this at the global level for a
* persistence unit. If anything, it could be a setting specific to
* a given embeddable class. But, four years after the introduction of
* this feature, it's still marked experimental and has multiple known
* unresolved bugs. It's therefore time for those who advocated for
* this feature to accept defeat.
*
* @since 5.1
*/
@Incubating
@Deprecated(since = "6")
String CREATE_EMPTY_COMPOSITES_ENABLED = "hibernate.create_empty_composites.enabled";
/**
* The {@link org.hibernate.annotations.Where @Where} annotation specifies a
* restriction on the table rows which are visible as entity class instances or
* collection elements.
* <p>
* This setting controls whether the restriction applied to an entity should be
* applied to association fetches (for one-to-one, many-to-one, one-to-many, and
* many-to-many associations) which target the entity.
*
* @apiNote The setting is very misnamed - it applies across all entity associations,
* not only to collections.
*
* @implSpec Enabled ({@code true}) by default, meaning the restriction is applied.
* When this setting is explicitly disabled ({@code false}), the restriction
* is not applied.
*
* @deprecated Originally added as a backwards compatibility flag
*/
@Remove
@Deprecated( forRemoval = true, since = "6.2" )
String USE_ENTITY_WHERE_CLAUSE_FOR_COLLECTIONS = "hibernate.use_entity_where_clause_for_collections";
/**
* Whether XML should be validated against their schema as Hibernate reads them.
*
* @settingDefault {@code true}
*
* @since 6.1
*/
String VALIDATE_XML = "hibernate.validate_xml";
/**
* Enables processing {@code hbm.xml} mappings by transforming them to {@code mapping.xml} and using
* that processor.
*
* @settingDefault {@code false} (opt-in).
*
* @since 6.1
*/
String TRANSFORM_HBM_XML = "hibernate.transform_hbm_xml.enabled";
/**
* How features in a {@code hbm.xml} file which are not supported for transformation
* should be handled. Valid values are defined by {@link UnsupportedFeatureHandling}
*
* @settingDefault {@link UnsupportedFeatureHandling#ERROR}
*
* @since 6.1
*/
String TRANSFORM_HBM_XML_FEATURE_HANDLING = "hibernate.transform_hbm_xml.unsupported_feature_handling";
/**
* @see org.hibernate.boot.MetadataBuilder#enableImplicitForcingOfDiscriminatorsInSelect
*
* @settingDefault {@code false}
*/
String FORCE_DISCRIMINATOR_IN_SELECTS_BY_DEFAULT = "hibernate.discriminator.force_in_select";
/**
* Controls whether Hibernate should infer a discriminator for entity hierarchies
* defined with joined inheritance.
* <p>
* Hibernate does not need a discriminator with joined inheritance. Therefore, its legacy
* behavior is to not infer a discriminator. However, some JPA providers do require
* discriminators with joined inheritance, so in the interest of portability this option
* has been added to Hibernate. When enabled ({@code true}), Hibernate will treat the absence
* of discriminator metadata as an indication to use the JPA defined defaults for discriminators.
*
* @implNote See Hibernate Jira issue HHH-6911 for additional background info.
*
* @settingDefault {@code false}
*
* @see org.hibernate.boot.MetadataBuilder#enableImplicitDiscriminatorsForJoinedSubclassSupport
* @see #IGNORE_EXPLICIT_DISCRIMINATOR_COLUMNS_FOR_JOINED_SUBCLASS
*/
String IMPLICIT_DISCRIMINATOR_COLUMNS_FOR_JOINED_SUBCLASS = "hibernate.discriminator.implicit_for_joined";
/**
* Controls whether Hibernate should ignore explicit discriminator metadata with
* joined inheritance.
* <p>
* Hibernate does not need a discriminator with joined inheritance. Historically
* it simply ignored discriminator metadata. When enabled ({@code true}), any
* discriminator metadata ({@link DiscriminatorColumn}, e.g.) is ignored allowing
* for backwards compatibility.
*
* @implNote See Hibernate Jira issue HHH-6911 for additional background info.
*
* @settingDefault {@code false}
*
* @see org.hibernate.boot.MetadataBuilder#enableExplicitDiscriminatorsForJoinedSubclassSupport
* @see #IMPLICIT_DISCRIMINATOR_COLUMNS_FOR_JOINED_SUBCLASS
*/
String IGNORE_EXPLICIT_DISCRIMINATOR_COLUMNS_FOR_JOINED_SUBCLASS = "hibernate.discriminator.ignore_explicit_for_joined";
/**
* By default, Hibernate maps character data represented by {@link String}s and
* {@link java.sql.Clob}s to the JDBC types {@link java.sql.Types#VARCHAR} and
* {@link java.sql.Types#CLOB}. This setting, when enabled, turns on the use of
* explicit nationalized character support for mappings involving character
* data, specifying that the JDBC types {@link java.sql.Types#NVARCHAR} and
* {@link java.sql.Types#NCLOB} should be used instead.
* <p>
* This setting is relevant for use with databases with
* {@linkplain org.hibernate.dialect.NationalizationSupport#EXPLICIT explicit
* nationalization support}, and it is not needed for databases whose native
* {@code varchar} and {@code clob} types support Unicode data. (If you're not
* sure how your database handles Unicode, check out the implementation of
* {@link Dialect#getNationalizationSupport()} for its
* SQL dialect.)
* <p>
* Enabling this setting has two effects:
* <ol>
* <li>when interacting with JDBC, Hibernate uses operations like
* {@link java.sql.PreparedStatement#setNString(int, String)}
* {@link java.sql.PreparedStatement#setNClob(int, java.sql.NClob)}
* to pass character data, and
* <li>when generating DDL, the schema export tool uses {@code nchar},
* {@code nvarchar}, or {@code nclob} as the generated column
* type when no column type is explicitly specified using
* {@link jakarta.persistence.Column#columnDefinition()}.
* </ol>
*
* @apiNote This is a global setting applying to all mappings associated with a given
* {@link SessionFactory}. The {@link Nationalized} annotation may be used to
* selectively enable nationalized character support for specific columns.
*
* @settingDefault {@code false} (disabled)
*
* @see org.hibernate.boot.MetadataBuilder#enableGlobalNationalizedCharacterDataSupport(boolean)
* @see Dialect#getNationalizationSupport
* @see Nationalized
*/
String USE_NATIONALIZED_CHARACTER_DATA = "hibernate.use_nationalized_character_data";
}

View File

@ -0,0 +1,47 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.cfg;
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
import org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider;
/**
* @author Steve Ebersole
*/
public interface MultiTenancySettings {
/**
* Specifies a {@link MultiTenantConnectionProvider}
* to use. Since {@code MultiTenantConnectionProvider} is also a service, it may be configured
* directly via the {@link org.hibernate.boot.registry.StandardServiceRegistryBuilder}.
*
* @since 4.1
*/
String MULTI_TENANT_CONNECTION_PROVIDER = "hibernate.multi_tenant_connection_provider";
/**
* Specifies a {@link CurrentTenantIdentifierResolver} to use,
* either:
* <ul>
* <li>an instance of {@code CurrentTenantIdentifierResolver},
* <li>a {@link Class} representing an class that implements {@code CurrentTenantIdentifierResolver}, or
* <li>the name of a class that implements {@code CurrentTenantIdentifierResolver}.
* </ul>
*
* @see org.hibernate.boot.SessionFactoryBuilder#applyCurrentTenantIdentifierResolver(CurrentTenantIdentifierResolver)
*
* @since 4.1
*/
String MULTI_TENANT_IDENTIFIER_RESOLVER = "hibernate.tenant_identifier_resolver";
/**
* During bootstrap, Hibernate needs access to any Connection for access to {@link java.sql.DatabaseMetaData}.
* <p/>
* This setting configures the name of the DataSource to use for this access
*/
String TENANT_IDENTIFIER_TO_USE_FOR_ANY_KEY = "hibernate.multi_tenant.datasource.identifier_for_any";
}

View File

@ -0,0 +1,185 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.cfg;
import org.hibernate.Incubating;
import org.hibernate.SessionFactoryObserver;
import jakarta.persistence.spi.PersistenceUnitInfo;
/**
* Settings related to persistence-units
*
* @author Steve Ebersole
*/
public interface PersistenceSettings {
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// JPA settings
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* Specifies a class implementing {@link jakarta.persistence.spi.PersistenceProvider}.
* Naturally, this should always be {@link org.hibernate.jpa.HibernatePersistenceProvider},
* which is the best damn persistence provider ever. There's no need to explicitly specify
* this setting when there are no inferior persistence providers floating about.
* <p>
* See JPA 2 sections 9.4.3 and 8.2.1.4
*/
String JAKARTA_PERSISTENCE_PROVIDER = "jakarta.persistence.provider";
/**
* Specifies the {@linkplain jakarta.persistence.spi.PersistenceUnitTransactionType
* type of transactions} supported by the entity managers. The default depends on
* whether the program is considered to be executing in a Java SE or EE environment:
* <ul>
* <li>For Java SE, the default is
* {@link jakarta.persistence.spi.PersistenceUnitTransactionType#RESOURCE_LOCAL
* RESOURCE_LOCAL}.
* <li>For Java EE, the default is
* {@link jakarta.persistence.spi.PersistenceUnitTransactionType#JTA JTA}.
* </ul>
* <p>
* See JPA 2 sections 9.4.3 and 8.2.1.2
*
* @see PersistenceUnitInfo#getTransactionType()
*/
String JAKARTA_TRANSACTION_TYPE = "jakarta.persistence.transactionType";
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Hibernate settings
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* Setting used to name the Hibernate {@link org.hibernate.SessionFactory}.
* <p>
* Naming the SessionFactory allows for it to be properly serialized across JVMs as
* long as the same name is used on each JVM.
* <p>
* If {@link #SESSION_FACTORY_NAME_IS_JNDI} is set to {@code true}, this is also the
* name under which the SessionFactory is bound into JNDI on startup and from which
* it can be obtained from JNDI.
*
* @see #SESSION_FACTORY_NAME_IS_JNDI
* @see org.hibernate.internal.SessionFactoryRegistry
* @see org.hibernate.boot.SessionFactoryBuilder#applyName(String)
*/
String SESSION_FACTORY_NAME = "hibernate.session_factory_name";
/**
* Does the value defined by {@link #SESSION_FACTORY_NAME} represent a JNDI namespace
* into which the {@link org.hibernate.SessionFactory} should be bound and made accessible?
* <p>
* Defaults to {@code true} for backwards compatibility.
* <p>
* Set this to {@code false} if naming a SessionFactory is needed for serialization purposes,
* but no writable JNDI context exists in the runtime environment or if the user simply does
* not want JNDI to be used.
*
* @see #SESSION_FACTORY_NAME
* @see org.hibernate.boot.SessionFactoryBuilder#applyNameAsJndiName(boolean)
*/
String SESSION_FACTORY_NAME_IS_JNDI = "hibernate.session_factory_name_is_jndi";
/**
* Specifies the name of the persistence unit.
*
* @see PersistenceUnitInfo#getPersistenceUnitName()
*/
String PERSISTENCE_UNIT_NAME = "hibernate.persistenceUnitName";
/**
* Specifies an implementation of {@link org.hibernate.boot.archive.scan.spi.Scanner},
* either:
* <ul>
* <li>an instance of {@code Scanner},
* <li>a {@link Class} representing a class that implements {@code Scanner}
* <li>the name of a class that implements {@code Scanner}.
* </ul>
*
* @see org.hibernate.boot.MetadataBuilder#applyScanner
*/
String SCANNER = "hibernate.archive.scanner";
/**
* Specifies an {@link org.hibernate.boot.archive.spi.ArchiveDescriptorFactory} to use
* in the scanning process, either:
* <ul>
* <li>an instance of {@code ArchiveDescriptorFactory},
* <li>a {@link Class} representing a class that implements {@code ArchiveDescriptorFactory}, or
* <li>the name of a class that implements {@code ArchiveDescriptorFactory}.
* </ul>
* <p>
* See information on {@link org.hibernate.boot.archive.scan.spi.Scanner}
* about expected constructor forms.
*
* @see #SCANNER
* @see org.hibernate.boot.archive.scan.spi.Scanner
* @see org.hibernate.boot.archive.scan.spi.AbstractScannerImpl
* @see org.hibernate.boot.MetadataBuilder#applyArchiveDescriptorFactory
*/
String SCANNER_ARCHIVE_INTERPRETER = "hibernate.archive.interpreter";
/**
* Identifies a comma-separated list of values indicating the types of things we should
* auto-detect during scanning. Allowable values include:
* <ul>
* <li>{@code "class"} specifies that {@code .class} files are discovered as managed classes
* <li>{@code "hbm"} specifies that {@code hbm.xml} files are discovered as mapping files
* </ul>
*
* @see org.hibernate.boot.MetadataBuilder#applyScanOptions
*/
String SCANNER_DISCOVERY = "hibernate.archive.autodetection";
/**
* Allows JPA callbacks (via {@link jakarta.persistence.PreUpdate} and friends) to be
* completely disabled. Mostly useful to save some memory when they are not used.
* <p>
* JPA callbacks are enabled by default. Set this property to {@code false} to disable
* them.
* <p>
* Experimental and will likely be removed as soon as the memory overhead is resolved.
*
* @see org.hibernate.jpa.event.spi.CallbackType
*
* @since 5.4
*/
@Incubating
String JPA_CALLBACKS_ENABLED = "hibernate.jpa_callbacks.enabled";
/**
* Specifies a class which implements {@link org.hibernate.SessionFactoryObserver} and has
* a constructor with no parameters.
*
* @see org.hibernate.boot.SessionFactoryBuilder#addSessionFactoryObservers(SessionFactoryObserver...)
*/
String SESSION_FACTORY_OBSERVER = "hibernate.session_factory_observer";
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Legacy JPA settings
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* @deprecated Use {@link #JAKARTA_PERSISTENCE_PROVIDER} instead
*/
@Deprecated
@SuppressWarnings("DeprecatedIsStillUsed")
String JPA_PERSISTENCE_PROVIDER = "javax.persistence.provider";
/**
* The type of transactions supported by the entity managers.
* <p>
* See JPA 2 sections 9.4.3 and 8.2.1.2
*
* @deprecated Use {@link #JAKARTA_TRANSACTION_TYPE} instead
*/
@Deprecated
String JPA_TRANSACTION_TYPE = "javax.persistence.transactionType";
}

View File

@ -0,0 +1,42 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.cfg;
/**
* @author Steve Ebersole
*/
public interface ProxoolSettings {
/**
* A setting prefix used to indicate settings that target the hibernate-proxool integration
*/
String PROXOOL_CONFIG_PREFIX = "hibernate.proxool";
/**
* Proxool property to configure the Proxool provider using an XML ({@code /path/to/file.xml})
*/
String PROXOOL_XML = "hibernate.proxool.xml";
/**
* Proxool property to configure the Proxool provider using a properties file
* ({@code /path/to/proxool.properties})
*/
String PROXOOL_PROPERTIES = "hibernate.proxool.properties";
/**
* Proxool property to configure the Proxool Provider from an already existing pool
* ({@code true} / {@code false})
*/
String PROXOOL_EXISTING_POOL = "hibernate.proxool.existing_pool";
/**
* Proxool property with the Proxool pool alias to use
* (Required for {@link #PROXOOL_EXISTING_POOL}, {@link #PROXOOL_PROPERTIES}, or
* {@link #PROXOOL_XML})
*/
String PROXOOL_POOL_ALIAS = "hibernate.proxool.pool_alias";
}

View File

@ -0,0 +1,225 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.cfg;
import org.hibernate.query.NullPrecedence;
import org.hibernate.query.spi.QueryPlan;
import jakarta.persistence.criteria.CriteriaDelete;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.CriteriaUpdate;
/**
* @author Steve Ebersole
*/
public interface QuerySettings {
/**
* Specifies a {@link org.hibernate.query.hql.HqlTranslator} to use for HQL query
* translation.
*/
String SEMANTIC_QUERY_PRODUCER = "hibernate.query.hql.translator";
/**
* Specifies a {@link org.hibernate.query.sqm.sql.SqmTranslatorFactory} to use for
* HQL query translation.
*/
String SEMANTIC_QUERY_TRANSLATOR = "hibernate.query.sqm.translator";
/**
* Defines the "global" strategy to use for handling HQL and Criteria mutation queries.
* Specifies a {@link org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy}..
*/
String QUERY_MULTI_TABLE_MUTATION_STRATEGY = "hibernate.query.mutation_strategy";
/**
* Defines the "global" strategy to use for handling HQL and Criteria insert queries.
* Specifies a {@link org.hibernate.query.sqm.mutation.spi.SqmMultiTableInsertStrategy}.
*/
String QUERY_MULTI_TABLE_INSERT_STRATEGY = "hibernate.query.insert_strategy";
/**
* When enabled, specifies that named queries be checked during startup.
* <p>
* By default, named queries are checked at startup.
* <p>
* Mainly intended for use in test environments.
*
* @see org.hibernate.boot.SessionFactoryBuilder#applyNamedQueryCheckingOnStartup(boolean)
*/
String QUERY_STARTUP_CHECKING = "hibernate.query.startup_check";
/**
* By default, a {@linkplain jakarta.persistence.criteria.CriteriaBuilder criteria
* query} produces SQL with a JDBC bind parameter for any value specified via the
* criteria query API, except when the value is passed via
* {@link jakarta.persistence.criteria.CriteriaBuilder#literal(Object)}, in which
* case the value is "inlined" as a SQL literal.
* <p>
* This setting may be used to override this default behavior:
* <ul>
* <li>the {@link org.hibernate.query.criteria.ValueHandlingMode#BIND "bind"}
* mode uses bind parameters to pass such values to JDBC, but
* <li>the {@link org.hibernate.query.criteria.ValueHandlingMode#INLINE "inline"}
* mode inlines values as SQL literals.
* </ul>
* <p>
* In both modes:
* <ul>
* <li>values specified using {@code literal()} are inlined, and
* <li>values specified using
* {@link jakarta.persistence.criteria.CriteriaBuilder#parameter(Class)} to create a
* {@link jakarta.persistence.criteria.ParameterExpression criteria parameter} and
* {@link jakarta.persistence.Query#setParameter(jakarta.persistence.Parameter,Object)}
* to specify its argument are passed to JDBC using a bind parameter.
* </ul>
* <p>
* The default mode is {@link org.hibernate.query.criteria.ValueHandlingMode#BIND}.
*
* @since 6.0.0
*
* @see org.hibernate.query.criteria.ValueHandlingMode
* @see jakarta.persistence.criteria.CriteriaBuilder#literal(Object)
* @see jakarta.persistence.criteria.CriteriaBuilder#parameter(Class)
* @see org.hibernate.query.criteria.HibernateCriteriaBuilder#value(Object)
*/
String CRITERIA_VALUE_HANDLING_MODE = "hibernate.criteria.value_handling_mode";
/**
* Specifies the default {@linkplain NullPrecedence precedence of null values} in the HQL
* {@code ORDER BY} clause, either {@code none}, {@code first}, or {@code last}.
* <p>
* The default is {@code none}.
*
* @see NullPrecedence
* @see org.hibernate.boot.SessionFactoryBuilder#applyDefaultNullPrecedence(NullPrecedence)
*/
String DEFAULT_NULL_ORDERING = "hibernate.order_by.default_null_ordering";
/**
* When enabled, specifies that {@linkplain org.hibernate.query.Query queries}
* created via {@link jakarta.persistence.EntityManager#createQuery(CriteriaQuery)},
* {@link jakarta.persistence.EntityManager#createQuery(CriteriaUpdate)} or
* {@link jakarta.persistence.EntityManager#createQuery(CriteriaDelete)} must
* create a copy of the passed criteria query object such that the resulting
* {@link jakarta.persistence.Query} object is not affected by mutation of the
* original {@linkplain CriteriaQuery criteria query}.
* <p>
* If disabled, it's assumed that the client does not mutate the criteria query
* after calling {@code createQuery()}. Thus, in the interest of performance, no
* copy is created.
* <p>
* The default behavior depends on how Hibernate is bootstrapped:
* <ul>
* <li>When bootstrapping Hibernate through the native bootstrap APIs, this setting
* is disabled, that is, no copy of the criteria query object is made.
* <li>When bootstrapping Hibernate through the JPA SPI, this setting is enabled so
* that criteria query objects are copied, as required by the JPA specification.
* </ul>
*
* @since 6.0
*/
String CRITERIA_COPY_TREE = "hibernate.criteria.copy_tree";
/**
* When {@linkplain org.hibernate.query.Query#setMaxResults(int) pagination} is used
* in combination with a {@code fetch join} applied to a collection or many-valued
* association, the limit must be applied in-memory instead of on the database. This
* typically has terrible performance characteristics, and should be avoided.
* <p>
* When enabled, this setting specifies that an exception should be thrown for any
* query which would result in the limit being applied in-memory.
* <p>
* By default, the exception is <em>disabled</em>, and the possibility of terrible
* performance is left as a problem for the client to avoid.
*
* @since 5.2.13
*/
String FAIL_ON_PAGINATION_OVER_COLLECTION_FETCH = "hibernate.query.fail_on_pagination_over_collection_fetch";
/**
* This setting defines how {@link org.hibernate.annotations.Immutable} entities
* are handled when executing a bulk update query. Valid options are enumerated
* by {@link org.hibernate.query.ImmutableEntityUpdateQueryHandlingMode}:
* <ul>
* <li>{@link org.hibernate.query.ImmutableEntityUpdateQueryHandlingMode#WARNING "warning"}
* specifies that a warning log message is issued when an
* {@linkplain org.hibernate.annotations.Immutable immutable} entity is to be
* updated via a bulk update statement, and
* <li>{@link org.hibernate.query.ImmutableEntityUpdateQueryHandlingMode#EXCEPTION "exception"}
* specifies that a {@link org.hibernate.HibernateException} should be thrown.
* </ul>
* <p>
* By default, a warning is logged.
*
* @since 5.2.17
*
* @see org.hibernate.query.ImmutableEntityUpdateQueryHandlingMode
*/
String IMMUTABLE_ENTITY_UPDATE_QUERY_HANDLING_MODE = "hibernate.query.immutable_entity_update_query_handling_mode";
/**
* Determines how parameters occurring in a SQL {@code IN} predicate are expanded.
* By default, the {@code IN} predicate expands to include sufficient bind parameters
* to accommodate the specified arguments.
* <p>
* However, for database systems supporting execution plan caching, there's a
* better chance of hitting the cache if the number of possible {@code IN} clause
* parameter list lengths is smaller.
* <p>
* When this setting is enabled, we expand the number of bind parameters to an
* integer power of two: 4, 8, 16, 32, 64. Thus, if 5, 6, or 7 arguments are bound
* to a parameter, a SQL statement with 8 bind parameters in the {@code IN} clause
* will be used, and null will be bound to the left-over parameters.
*
* @since 5.2.17
*/
String IN_CLAUSE_PARAMETER_PADDING = "hibernate.query.in_clause_parameter_padding";
/**
* When enabled, specifies that Hibernate should attempt to map parameter names
* given in a {@link org.hibernate.procedure.ProcedureCall} or
* {@link jakarta.persistence.StoredProcedureQuery} to named parameters of the
* JDBC {@link java.sql.CallableStatement}.
*
* @see org.hibernate.boot.spi.SessionFactoryOptions#isUseOfJdbcNamedParametersEnabled()
*
* @since 6.0
*/
String CALLABLE_NAMED_PARAMS_ENABLED = "hibernate.query.proc.callable_named_params_enabled";
/**
* When enabled, specifies that {@linkplain QueryPlan query plans} should be
* {@linkplain org.hibernate.query.spi.QueryInterpretationCache cached}.
* <p>
* By default, the query plan cache is disabled, unless one of the configuration
* properties {@value #QUERY_PLAN_CACHE_MAX_SIZE} or
* {@value #QUERY_PLAN_CACHE_PARAMETER_METADATA_MAX_SIZE} is set.
*/
String QUERY_PLAN_CACHE_ENABLED = "hibernate.query.plan_cache_enabled";
/**
* The maximum number of entries in the
* {@linkplain org.hibernate.query.spi.QueryInterpretationCache
* query interpretation cache}.
* <p>
* The default maximum is
* {@value org.hibernate.query.spi.QueryEngine#DEFAULT_QUERY_PLAN_MAX_COUNT}.
*
* @see org.hibernate.query.spi.QueryInterpretationCache
*/
String QUERY_PLAN_CACHE_MAX_SIZE = "hibernate.query.plan_cache_max_size";
/**
* The maximum number of {@link org.hibernate.query.ParameterMetadata} instances
* maintained by the {@link org.hibernate.query.spi.QueryInterpretationCache}.
* <p>
*
* @deprecated this setting is not currently used
*/
@Deprecated(since="6.0")
String QUERY_PLAN_CACHE_PARAMETER_METADATA_MAX_SIZE = "hibernate.query.plan_parameter_metadata_max_size";
}

View File

@ -0,0 +1,468 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.cfg;
import org.hibernate.query.sqm.mutation.internal.temptable.GlobalTemporaryTableStrategy;
import org.hibernate.query.sqm.mutation.internal.temptable.LocalTemporaryTableStrategy;
import org.hibernate.query.sqm.mutation.internal.temptable.PersistentTableStrategy;
import org.hibernate.tool.schema.UniqueConstraintSchemaUpdateStrategy;
/**
* @author Steve Ebersole
*/
public interface SchemaToolingSettings {
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// JPA settings
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* Specifies what type of schema tooling action should be performed against the
* database specified using either {@value JdbcSettings#JAKARTA_HBM2DDL_CONNECTION} or the
* configured {@link org.hibernate.engine.jdbc.connections.spi.ConnectionProvider}
* for the {@link org.hibernate.SessionFactory}.
* <p>
* Valid options are enumerated by {@link org.hibernate.tool.schema.Action}.
* <p>
* This setting takes precedence over {@value #HBM2DDL_AUTO}.
* <p>
* If no value is specified, the default is
* {@link org.hibernate.tool.schema.Action#NONE "none"}.
*
* @see org.hibernate.tool.schema.Action
* @see JdbcSettings#JAKARTA_HBM2DDL_CONNECTION
* @see JdbcSettings#JAKARTA_JDBC_URL
*/
String JAKARTA_HBM2DDL_DATABASE_ACTION = "jakarta.persistence.schema-generation.database.action";
/**
* Specifies what type of schema tooling action should be written to script files.
* <p>
* Valid options are enumerated by {@link org.hibernate.tool.schema.Action}.
* <p>
* The script file is identified using {@value #JAKARTA_HBM2DDL_SCRIPTS_CREATE_TARGET}.
* <p>
* If no value is specified, the default is
* {@link org.hibernate.tool.schema.Action#NONE "none"}.
*
* @see org.hibernate.tool.schema.Action
* @see #JAKARTA_HBM2DDL_SCRIPTS_CREATE_TARGET
* @see #JAKARTA_HBM2DDL_SCRIPTS_DROP_TARGET
*/
String JAKARTA_HBM2DDL_SCRIPTS_ACTION = "jakarta.persistence.schema-generation.scripts.action";
/**
* Specifies whether schema generation commands for schema creation are to be determined
* based on object/relational mapping metadata, DDL scripts, or a combination of the two.
* See {@link org.hibernate.tool.schema.SourceType} for the list of legal values.
* <p>
* If no value is specified, a default is inferred as follows:
* <ul>
* <li>if source scripts are specified via {@value #JAKARTA_HBM2DDL_CREATE_SCRIPT_SOURCE},
* then {@link org.hibernate.tool.schema.SourceType#SCRIPT "script"} is assumed, or
* <li>otherwise, {@link org.hibernate.tool.schema.SourceType#SCRIPT "metadata"} is
* assumed.
* </ul>
*
* @see org.hibernate.tool.schema.SourceType
*/
String JAKARTA_HBM2DDL_CREATE_SOURCE = "jakarta.persistence.schema-generation.create-source";
/**
* Specifies whether schema generation commands for schema dropping are to be determined
* based on object/relational mapping metadata, DDL scripts, or a combination of the two.
* See {@link org.hibernate.tool.schema.SourceType} for the list of legal values.
* <p>
* If no value is specified, a default is inferred as follows:
* <ul>
* <li>if source scripts are specified via {@value #JAKARTA_HBM2DDL_DROP_SCRIPT_SOURCE},
* then {@linkplain org.hibernate.tool.schema.SourceType#SCRIPT "script"} is assumed, or
* <li>otherwise, {@linkplain org.hibernate.tool.schema.SourceType#SCRIPT "metadata"}
* is assumed.
* </ul>
*
* @see org.hibernate.tool.schema.SourceType
*/
String JAKARTA_HBM2DDL_DROP_SOURCE = "jakarta.persistence.schema-generation.drop-source";
/**
* Specifies the CREATE script file as either a {@link java.io.Reader} configured for reading
* the DDL script file or a string designating a file {@link java.net.URL} for the DDL script.
* <p>
* Hibernate historically also accepted {@link #HBM2DDL_IMPORT_FILES} for a similar purpose.
* This setting is now preferred.
*
* @see #JAKARTA_HBM2DDL_CREATE_SOURCE
* @see #HBM2DDL_IMPORT_FILES
*/
String JAKARTA_HBM2DDL_CREATE_SCRIPT_SOURCE = "jakarta.persistence.schema-generation.create-script-source";
/**
* Specifies the DROP script file as either a {@link java.io.Reader} configured for reading
* the DDL script file or a string designating a file {@link java.net.URL} for the DDL script.
*
* @see #JAKARTA_HBM2DDL_DROP_SOURCE
*/
String JAKARTA_HBM2DDL_DROP_SCRIPT_SOURCE = "jakarta.persistence.schema-generation.drop-script-source";
/**
* For cases where {@value #JAKARTA_HBM2DDL_SCRIPTS_ACTION} indicates that schema creation
* commands should be written to a script file, this setting specifies either a
* {@link java.io.Writer} configured for output of the DDL script or a string specifying
* the file URL for the DDL script.
*
* @see #JAKARTA_HBM2DDL_SCRIPTS_ACTION
*/
String JAKARTA_HBM2DDL_SCRIPTS_CREATE_TARGET = "jakarta.persistence.schema-generation.scripts.create-target";
/**
* For cases where {@value #JAKARTA_HBM2DDL_SCRIPTS_ACTION} indicates that schema
* drop commands should be written to a script file, this setting specifies either a
* {@link java.io.Writer} configured for output of the DDL script or a string
* specifying the file URL for the DDL script.
*
* @see #JAKARTA_HBM2DDL_SCRIPTS_ACTION
*/
String JAKARTA_HBM2DDL_SCRIPTS_DROP_TARGET = "jakarta.persistence.schema-generation.scripts.drop-target";
/**
* JPA-standard variant of {@link #HBM2DDL_IMPORT_FILES} for specifying a database
* initialization script to be run as part of schema-export
* <p>
* Specifies a {@link java.io.Reader} configured for reading of the SQL load script
* or a string designating the {@link java.net.URL} for the SQL load script.
*/
String JAKARTA_HBM2DDL_LOAD_SCRIPT_SOURCE = "jakarta.persistence.sql-load-script-source";
/**
* The JPA variant of {@link #HBM2DDL_CREATE_NAMESPACES} used to specify whether database
* schemas used in the mapping model should be created on export in addition to creating
* the tables, sequences, etc.
* <p>
* The default is {@code false}, meaning to not create schemas
*/
String JAKARTA_HBM2DDL_CREATE_SCHEMAS = "jakarta.persistence.create-database-schemas";
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Hibernate settings
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* Specifies the {@link org.hibernate.tool.schema.spi.SchemaManagementTool} to use for
* performing schema management.
* <p>
* By default, {@link org.hibernate.tool.schema.internal.HibernateSchemaManagementTool}
* is used.
*
* @since 5.0
*/
String SCHEMA_MANAGEMENT_TOOL = "hibernate.schema_management_tool";
/**
* Setting to perform {@link org.hibernate.tool.schema.spi.SchemaManagementTool}
* actions automatically as part of the {@link org.hibernate.SessionFactory}
* lifecycle. Valid options are enumerated by {@link org.hibernate.tool.schema.Action}.
* <p>
* Interpreted in combination with {@link #JAKARTA_HBM2DDL_DATABASE_ACTION} and
* {@link #JAKARTA_HBM2DDL_SCRIPTS_ACTION}. If no value is specified, the default
* is {@linkplain org.hibernate.tool.schema.Action#NONE "none"}.
*
* @settingDefault {@code "none"}
*
* @see org.hibernate.tool.schema.Action
*/
String HBM2DDL_AUTO = "hibernate.hbm2ddl.auto";
/**
* For cases where the {@value #JAKARTA_HBM2DDL_SCRIPTS_ACTION} value indicates that schema commands
* should be written to DDL script file, specifies if schema commands should be appended to
* the end of the file rather than written at the beginning of the file.
* <p>
* Values are: {@code true} for appending schema commands to the end of the file, {@code false}
* for writing schema commands at the beginning.
*
* @settingDefault {@code true}
*/
String HBM2DDL_SCRIPTS_CREATE_APPEND = "hibernate.hbm2ddl.schema-generation.script.append";
/**
* The {@link org.hibernate.tool.schema.spi.SqlScriptCommandExtractor} implementation
* to use for parsing source/import files specified by {@link #JAKARTA_HBM2DDL_CREATE_SCRIPT_SOURCE},
* {@link #JAKARTA_HBM2DDL_DROP_SCRIPT_SOURCE} or {@link #HBM2DDL_IMPORT_FILES}. Either:
* <ul>
* <li>an instance of {@link org.hibernate.tool.schema.spi.SqlScriptCommandExtractor},
* <li>a {@link Class} object representing a class that implements {@code SqlScriptCommandExtractor},
* or
* <li>the name of a class that implements {@code SqlScriptCommandExtractor}.
* </ul>
* <p>
* The correct extractor to use depends on the format of the SQL script:
* <ul>
* <li>if the script has one complete SQL statement per line, use
* {@link org.hibernate.tool.schema.internal.script.SingleLineSqlScriptExtractor}, or
* <li>if a script contains statements spread over multiple lines, use
* {@link org.hibernate.tool.schema.internal.script.MultiLineSqlScriptExtractor}.
* </ul>
*
* @settingDefault {@code org.hibernate.tool.schema.internal.script.SingleLineSqlScriptExtractor}.
*
* @see org.hibernate.tool.schema.internal.script.SingleLineSqlScriptExtractor
* @see org.hibernate.tool.schema.internal.script.MultiLineSqlScriptExtractor
*/
String HBM2DDL_IMPORT_FILES_SQL_EXTRACTOR = "hibernate.hbm2ddl.import_files_sql_extractor";
/**
* Used to specify the {@link org.hibernate.tool.schema.spi.SchemaFilterProvider} to be
* used by create, drop, migrate and validate operations on the database schema. A
* {@code SchemaFilterProvider} provides filters that can be used to limit the scope of
* these operations to specific namespaces, tables and sequences. All objects are
* included by default.
*
* @since 5.1
*/
String HBM2DDL_FILTER_PROVIDER = "hibernate.hbm2ddl.schema_filter_provider";
/**
* Setting to choose the strategy used to access the JDBC Metadata.
* <p>
* Valid options are defined by {@link org.hibernate.tool.schema.JdbcMetadaAccessStrategy}.
* {@link org.hibernate.tool.schema.JdbcMetadaAccessStrategy#GROUPED} is the default.
*
* @settingDefault Grouped, unless {@value #ENABLE_SYNONYMS} is enabled
*
* @see org.hibernate.tool.schema.JdbcMetadaAccessStrategy
*/
String HBM2DDL_JDBC_METADATA_EXTRACTOR_STRATEGY = "hibernate.hbm2ddl.jdbc_metadata_extraction_strategy";
/**
* Identifies the delimiter to use to separate schema management statements in script
* outputs.
*
* @settingDefault {@code ;}
*/
String HBM2DDL_DELIMITER = "hibernate.hbm2ddl.delimiter";
/**
* The name of the charset used by the schema generation resource.
* <p>
* By default, the JVM default charset is used.
*
* @since 5.2.3
*/
String HBM2DDL_CHARSET_NAME = "hibernate.hbm2ddl.charset_name";
/**
* When enabled, specifies that the schema migration tool should halt on any error,
* terminating the bootstrap process.
*
* @settingDefault {@code false}
*
* @since 5.2.4
*/
String HBM2DDL_HALT_ON_ERROR = "hibernate.hbm2ddl.halt_on_error";
/**
* Used with the {@link jakarta.persistence.ConstraintMode#PROVIDER_DEFAULT}
* strategy for foreign key mapping.
* <p>
* Valid values are {@link jakarta.persistence.ConstraintMode#CONSTRAINT} and
* {@link jakarta.persistence.ConstraintMode#NO_CONSTRAINT}.
*
* @settingDefault {@link jakarta.persistence.ConstraintMode#CONSTRAINT}.
*
* @since 5.4
*/
String HBM2DDL_DEFAULT_CONSTRAINT_MODE = "hibernate.hbm2ddl.default_constraint_mode";
/**
* Specifies the default storage engine for a relational databases that supports
* multiple storage engines. This property must be set either as an {@link Environment}
* variable or JVM System Property, since the {@link org.hibernate.dialect.Dialect} is
* instantiated before Hibernate property resolution.
*
* @since 5.2.9
*/
String STORAGE_ENGINE = "hibernate.dialect.storage_engine";
/**
* If enabled, allows schema update and validation to support synonyms. Due
* to the possibility that this would return duplicate tables (especially in
* Oracle), this is disabled by default.
*
* @settingDefault {@code false}
*/
String ENABLE_SYNONYMS = "hibernate.synonyms";
/**
* Specifies a comma-separated list of extra table types, in addition to the
* default types {@code "TABLE"} and {@code "VIEW"}, to recognize as physical
* tables when performing schema update, creation and validation.
*
* @since 5.0
*/
String EXTRA_PHYSICAL_TABLE_TYPES = "hibernate.hbm2ddl.extra_physical_table_types";
/**
* Unique columns and unique keys both use unique constraints in most dialects.
* The schema exporter must create these constraints, but database support for
* finding existing constraints is extremely inconsistent. Worse, unique constraints
* without explicit names are assigned names with randomly generated characters.
* <p>
* Therefore, select from these strategies:
* <ul>
* <li>{@linkplain UniqueConstraintSchemaUpdateStrategy#DROP_RECREATE_QUIETLY DROP_RECREATE_QUIETLY}:
* Attempt to drop, then (re-)create each unique constraint, ignoring any exceptions thrown.
* This is the default.
* <li>{@linkplain UniqueConstraintSchemaUpdateStrategy#RECREATE_QUIETLY RECREATE_QUIETLY}:
* Attempt to (re-)create unique constraints, ignoring exceptions thrown if the constraint already existed.
* <li>{@linkplain UniqueConstraintSchemaUpdateStrategy#SKIP SKIP}:
* Do not attempt to create unique constraints on a schema update.
* </ul>
*
* @settingDefault {@linkplain UniqueConstraintSchemaUpdateStrategy#DROP_RECREATE_QUIETLY DROP_RECREATE_QUIETLY}
*/
String UNIQUE_CONSTRAINT_SCHEMA_UPDATE_STRATEGY = "hibernate.schema_update.unique_constraint_strategy";
/**
* Allows creation of {@linkplain org.hibernate.dialect.temptable.TemporaryTableKind#PERSISTENT persistent}
* temporary tables at application startup to be disabled. By default, table creation is enabled.
*/
String BULK_ID_STRATEGY_PERSISTENT_TEMPORARY_CREATE_TABLES = PersistentTableStrategy.CREATE_ID_TABLES;
/**
* Allows dropping of {@linkplain org.hibernate.dialect.temptable.TemporaryTableKind#PERSISTENT persistent}
* temporary tables at application shutdown to be disabled. By default, table dropping is enabled.
*/
String BULK_ID_STRATEGY_PERSISTENT_TEMPORARY_DROP_TABLES = PersistentTableStrategy.DROP_ID_TABLES;
/**
* Allows creation of {@linkplain org.hibernate.dialect.temptable.TemporaryTableKind#GLOBAL global}
* temporary tables at application startup to be disabled. By default, table creation is enabled.
*/
String BULK_ID_STRATEGY_GLOBAL_TEMPORARY_CREATE_TABLES = GlobalTemporaryTableStrategy.CREATE_ID_TABLES;
/**
* Allows dropping of {@linkplain org.hibernate.dialect.temptable.TemporaryTableKind#GLOBAL global}
* temporary tables at application shutdown to be disabled. By default, table dropping is enabled.
*/
String BULK_ID_STRATEGY_GLOBAL_TEMPORARY_DROP_TABLES = GlobalTemporaryTableStrategy.DROP_ID_TABLES;
/**
* Allows dropping of {@linkplain org.hibernate.dialect.temptable.TemporaryTableKind#LOCAL local}
* temporary tables at transaction commit to be enabled. By default, table dropping is disabled,
* and the database will drop the temporary tables automatically.
*/
String BULK_ID_STRATEGY_LOCAL_TEMPORARY_DROP_TABLES = LocalTemporaryTableStrategy.DROP_ID_TABLES;
/**
* Specifies a comma-separated list of file names of scripts containing SQL DML statements that
* should be executed after schema export completes. The order of the scripts is significant,
* with the first script in the list being executed first.
* <p>
* The scripts are only executed if the schema is created by Hibernate, that is, if
* {@value #HBM2DDL_AUTO} is set to {@code create} or {@code create-drop}.
* <p>
* The default value is {@code /import.sql}.
*
* @deprecated The JPA-standard setting {@link #JAKARTA_HBM2DDL_CREATE_SCRIPT_SOURCE} is now preferred.
*/
@Deprecated
String HBM2DDL_IMPORT_FILES = "hibernate.hbm2ddl.import_files";
/**
* Specifies whether to automatically create also the database schema/catalog.
* The default is false.
*
* @since 5.0
*
* @deprecated The JPA-standard setting {@link #JAKARTA_HBM2DDL_CREATE_SCHEMAS} is now preferred.
*/
@Deprecated
@SuppressWarnings("DeprecatedIsStillUsed")
String HBM2DDL_CREATE_NAMESPACES = "hibernate.hbm2ddl.create_namespaces";
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Legacy JPA settings
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* @deprecated Use {@link #JAKARTA_HBM2DDL_DATABASE_ACTION} instead
*/
@Deprecated
@SuppressWarnings("DeprecatedIsStillUsed")
String HBM2DDL_DATABASE_ACTION = "javax.persistence.schema-generation.database.action";
/**
* @deprecated Use {@link #JAKARTA_HBM2DDL_SCRIPTS_ACTION} instead
*/
@Deprecated
@SuppressWarnings("DeprecatedIsStillUsed")
String HBM2DDL_SCRIPTS_ACTION = "javax.persistence.schema-generation.scripts.action";
/**
* @deprecated Migrate to {@link #JAKARTA_HBM2DDL_CREATE_SOURCE} instead
* @see org.hibernate.tool.schema.SourceType
*/
@Deprecated
@SuppressWarnings("DeprecatedIsStillUsed")
String HBM2DDL_CREATE_SOURCE = "javax.persistence.schema-generation.create-source";
/**
* @deprecated Migrate to {@link #JAKARTA_HBM2DDL_DROP_SOURCE}.
* @see org.hibernate.tool.schema.SourceType
*/
@Deprecated
@SuppressWarnings("DeprecatedIsStillUsed")
String HBM2DDL_DROP_SOURCE = "javax.persistence.schema-generation.drop-source";
/**
* @deprecated Migrate to {@link #JAKARTA_HBM2DDL_CREATE_SCRIPT_SOURCE}
*/
@Deprecated
@SuppressWarnings("DeprecatedIsStillUsed")
String HBM2DDL_CREATE_SCRIPT_SOURCE = "javax.persistence.schema-generation.create-script-source";
/**
* @deprecated Migrate to {@link #JAKARTA_HBM2DDL_DROP_SCRIPT_SOURCE}
*/
@Deprecated
@SuppressWarnings("DeprecatedIsStillUsed")
String HBM2DDL_DROP_SCRIPT_SOURCE = "javax.persistence.schema-generation.drop-script-source";
/**
* @deprecated Migrate to {@link #JAKARTA_HBM2DDL_SCRIPTS_CREATE_TARGET}
*/
@Deprecated
@SuppressWarnings("DeprecatedIsStillUsed")
String HBM2DDL_SCRIPTS_CREATE_TARGET = "javax.persistence.schema-generation.scripts.create-target";
/**
* @deprecated Migrate to {@link #JAKARTA_HBM2DDL_SCRIPTS_DROP_TARGET}
*/
@Deprecated
@SuppressWarnings("DeprecatedIsStillUsed")
String HBM2DDL_SCRIPTS_DROP_TARGET = "javax.persistence.schema-generation.scripts.drop-target";
/**
* @deprecated Use {@link #JAKARTA_HBM2DDL_LOAD_SCRIPT_SOURCE} instead
*/
@Deprecated
@SuppressWarnings("DeprecatedIsStillUsed")
String HBM2DDL_LOAD_SCRIPT_SOURCE = "javax.persistence.sql-load-script-source";
/**
* @deprecated Use {@link #JAKARTA_HBM2DDL_CREATE_SCHEMAS} instead
*/
@Deprecated
@SuppressWarnings("DeprecatedIsStillUsed")
String HBM2DDL_CREATE_SCHEMAS = "javax.persistence.create-database-schemas";
}

View File

@ -0,0 +1,80 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.cfg;
import java.util.function.Supplier;
import org.hibernate.Interceptor;
/**
* @author Steve Ebersole
*/
public interface SessionEventSettings {
/**
* Controls whether {@linkplain org.hibernate.stat.SessionStatistics session metrics}
* should be {@linkplain org.hibernate.engine.internal.StatisticalLoggingSessionEventListener
* logged} for any session in which statistics are being collected.
* <p>
* By default, logging of session metrics is disabled unless {@link StatisticsSettings#GENERATE_STATISTICS}
* is enabled.
*
* @settingDefault Defined by {@link StatisticsSettings#GENERATE_STATISTICS}
*/
String LOG_SESSION_METRICS = "hibernate.session.events.log";
/**
* Defines a default {@link org.hibernate.SessionEventListener} to be applied to
* newly-opened {@link org.hibernate.Session}s.
*/
String AUTO_SESSION_EVENTS_LISTENER = "hibernate.session.events.auto";
/**
* Specifies an {@link org.hibernate.Interceptor} implementation associated with
* the {@link org.hibernate.SessionFactory} and propagated to each {@code Session}
* created from the {@code SessionFactory}. Either:
* <ul>
* <li>an instance of {@code Interceptor},
* <li>a {@link Class} representing a class that implements {@code Interceptor}, or
* <li>the name of a class that implements {@code Interceptor}.
* </ul>
* <p>
* This setting identifies an {@code Interceptor} which is effectively a singleton
* across all the sessions opened from the {@code SessionFactory} to which it is
* applied; the same instance will be passed to each {@code Session}. If there
* should be a separate instance of {@code Interceptor} for each {@code Session},
* use {@link #SESSION_SCOPED_INTERCEPTOR} instead.
*
* @see org.hibernate.boot.SessionFactoryBuilder#applyInterceptor(Interceptor)
*
* @since 5.0
*/
String INTERCEPTOR = "hibernate.session_factory.interceptor";
/**
* Specifies an {@link org.hibernate.Interceptor} implementation associated with
* the {@link org.hibernate.SessionFactory} and propagated to each {@code Session}
* created from the {@code SessionFactory}. Either:
* <ul>
* <li>a {@link Class} representing a class that implements {@code Interceptor},
* <li>the name of a class that implements {@code Interceptor}, or
* <li>an instance of {@link Supplier} used to obtain the interceptor.
* </ul>
* <p>
* Note that this setting cannot specify an {@code Interceptor} instance.
* <p>
* This setting identifies an {@code Interceptor} implementation that is to be
* applied to every {@code Session} opened from the {@code SessionFactory}, but
* unlike {@link #INTERCEPTOR}, a separate instance created for each {@code Session}.
*
* @see org.hibernate.boot.SessionFactoryBuilder#applyStatelessInterceptor(Class)
* @see org.hibernate.boot.SessionFactoryBuilder#applyStatelessInterceptor(Supplier)
*
* @since 5.2
*/
String SESSION_SCOPED_INTERCEPTOR = "hibernate.session_factory.session_scoped_interceptor";
}

View File

@ -0,0 +1,46 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.cfg;
import org.hibernate.stat.spi.StatisticsFactory;
/**
* @author Steve Ebersole
*/
public interface StatisticsSettings {
/**
* When enabled, specifies that {@linkplain org.hibernate.stat.Statistics statistics}
* should be collected.
*
* @settingDefault {@code false}
*
* @see org.hibernate.boot.SessionFactoryBuilder#applyStatisticsSupport(boolean)
*/
String GENERATE_STATISTICS = "hibernate.generate_statistics";
/**
* When statistics are {@linkplain #GENERATE_STATISTICS enabled}, names the
* {@link StatisticsFactory} to use. Recognizes a class name as well as an instance of
* {@link StatisticsFactory}.
* <p/>
* Allows customization of how the Hibernate Statistics are collected.
*/
String STATS_BUILDER = "hibernate.stats.factory";
/**
* This setting controls the number of {@link org.hibernate.stat.QueryStatistics}
* entries that will be stored by the Hibernate {@link org.hibernate.stat.Statistics}
* object.
* <p>
* The default value is {@value org.hibernate.stat.Statistics#DEFAULT_QUERY_STATISTICS_MAX_SIZE}.
*
* @since 5.4
*
* @see org.hibernate.stat.Statistics#getQueries()
*/
String QUERY_STATISTICS_MAX_SIZE = "hibernate.statistics.query_max_size";
}

View File

@ -0,0 +1,181 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.cfg;
import jakarta.persistence.spi.PersistenceUnitInfo;
/**
* @author Steve Ebersole
*/
public interface TransactionSettings {
/**
* Specify the {@link org.hibernate.resource.transaction.spi.TransactionCoordinatorBuilder}
* implementation to use for creating instances of
* {@link org.hibernate.resource.transaction.spi.TransactionCoordinator} which the interface
* Hibernate uses to manage transactions.
* <p/>
* Accepts either:
* <ul>
* <li>an instance of {@code TransactionCoordinatorBuilder},
* <li>a {@link Class} representing a class that implements {@code TransactionCoordinatorBuilder},
* <li>the name of a class that implements {@code TransactionCoordinatorBuilder},
* <li>{@code jta} or {@code jdbc}</li>
* </ul>
* <p/>
*
* @settingDefault With Jakarta Persistence bootstrapping, based on the persistence unit's {@link PersistenceUnitInfo#getTransactionType()};
* otherwise {@code jdbc}.
*
* @implSpec With non Jakarta Persistence bootstrapping, Hibernate will use {@code jdbc} as the default which
* will cause problems if the application actually uses JTA-based transactions.
*
* @see #JTA_PLATFORM
*
* @since 5.0
*/
String TRANSACTION_COORDINATOR_STRATEGY = "hibernate.transaction.coordinator_class";
/**
* Specifies the {@link org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform}
* implementation to use for integrating with JTA, either:
* <ul>
* <li>an instance of {@code JtaPlatform}, or
* <li>the name of a class that implements {@code JtaPlatform}.
* <li>short name of a class (sans package name) that implements {@code JtaPlatform}.
* </ul>
*
* @see #JTA_PLATFORM_RESOLVER
*
* @since 4.0
*/
String JTA_PLATFORM = "hibernate.transaction.jta.platform";
/**
* Specifies a {@link org.hibernate.engine.transaction.jta.platform.spi.JtaPlatformResolver}
* implementation that should be used to obtain an instance of
* {@link org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform}.
*
* @since 4.3
*/
String JTA_PLATFORM_RESOLVER = "hibernate.transaction.jta.platform_resolver";
/**
* When enabled, specifies that the {@link jakarta.transaction.UserTransaction} should
* be used in preference to the {@link jakarta.transaction.TransactionManager} for JTA
* transaction management.
* <p>
* By default, the {@code TransactionManager} is preferred.
*
* @see org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform#retrieveUserTransaction
* @see org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform#retrieveTransactionManager
*
* @see org.hibernate.boot.SessionFactoryBuilder#applyPreferUserTransactions(boolean)
*
* @settingDefault {@code false} as {@code TransactionManager} is preferred.
*
* @since 5.0
*/
String PREFER_USER_TRANSACTION = "hibernate.jta.prefer_user_transaction";
/**
* When enabled, indicates that it is safe to cache {@link jakarta.transaction.TransactionManager}
* references in the {@link org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform}
*
* @settingDefault Generally {@code true}, though {@code JtaPlatform} implementations
* can do their own thing.
*
* @since 4.0
*/
String JTA_CACHE_TM = "hibernate.jta.cacheTransactionManager";
/**
* When enabled, indicates that it is safe to cache {@link jakarta.transaction.UserTransaction}
* references in the {@link org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform}
*
* @settingDefault Generally {@code true}, though {@code JtaPlatform} implementations
* can do their own thing.
*
* @since 4.0
*/
String JTA_CACHE_UT = "hibernate.jta.cacheUserTransaction";
/**
* A transaction can be rolled back by another thread ("tracking by thread")
* -- not the original application. Examples of this include a JTA
* transaction timeout handled by a background reaper thread. The ability
* to handle this situation requires checking the Thread ID every time
* Session is called. This can certainly have performance considerations.
*
* @settingDefault {@code true} (enabled).
*
* @see org.hibernate.boot.SessionFactoryBuilder#applyJtaTrackingByThread(boolean)
*/
String JTA_TRACK_BY_THREAD = "hibernate.jta.track_by_thread";
/**
* When enabled, allows access to the {@link org.hibernate.Transaction} even when
* using a JTA for transaction management.
* <p>
* Values are {@code true}, which grants access, and {@code false}, which does not.
* <p>
*
* @settingDefault {@code false} when bootstrapped via JPA; {@code true} otherwise.
*
* @see JpaComplianceSettings#JPA_TRANSACTION_COMPLIANCE
*/
String ALLOW_JTA_TRANSACTION_ACCESS = "hibernate.jta.allowTransactionAccess";
/**
* Allows a detached proxy or lazy collection to be fetched even when not
* associated with an open persistence context, by creating a temporary
* persistence context when the proxy or collection is accessed. This
* behavior is not recommended, since it can easily break transaction
* isolation or lead to data aliasing; it is therefore disabled by default.
*
* @settingDefault {@code false} (disabled)
*
* @see org.hibernate.boot.SessionFactoryBuilder#applyLazyInitializationOutsideTransaction(boolean)
*/
String ENABLE_LAZY_LOAD_NO_TRANS = "hibernate.enable_lazy_load_no_trans";
/**
* When enabled, allows update operations outside a transaction.
* <p>
* Since version 5.2 Hibernate conforms with the JPA specification and disallows
* flushing any update outside a transaction.
* <p>
* Values are {@code true}, which allows flushing outside a transaction, and
* {@code false}, which does not.
* <p>
* The default behavior is to disallow update operations outside a transaction.
*
* @see org.hibernate.boot.SessionFactoryBuilder#allowOutOfTransactionUpdateOperations(boolean)
*
* @since 5.2
*/
String ALLOW_UPDATE_OUTSIDE_TRANSACTION = "hibernate.allow_update_outside_transaction";
/**
* When enabled, specifies that the {@link org.hibernate.Session} should be
* closed automatically at the end of each transaction.
*
* @settingDefault {@code false}
*
* @see org.hibernate.boot.SessionFactoryBuilder#applyAutoClosing(boolean)
*/
String AUTO_CLOSE_SESSION = "hibernate.transaction.auto_close_session";
/**
* When enabled, specifies that automatic flushing should occur during the JTA
* {@link jakarta.transaction.Synchronization#beforeCompletion()} callback.
*
* @settingDefault {@code true} unless using JPA bootstrap
*
* @see org.hibernate.boot.SessionFactoryBuilder#applyAutoFlushing(boolean)
*/
String FLUSH_BEFORE_COMPLETION = "hibernate.transaction.flush_before_completion";
}

View File

@ -0,0 +1,111 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.cfg;
/**
* @author Steve Ebersole
*/
public interface ValidationSettings {
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// JPA settings
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* Indicates which {@linkplain jakarta.persistence.ValidationMode form of automatic
* validation} is in effect as per the rules defined in JPA 2 section 3.6.1.1.
* <p>
* See JPA 2 sections 9.4.3 and 8.2.1.8
*
* @see jakarta.persistence.ValidationMode
*/
String JAKARTA_VALIDATION_MODE = "jakarta.persistence.validation.mode";
/**
* Used to pass along any discovered {@link jakarta.validation.ValidatorFactory}.
*
* @see org.hibernate.boot.SessionFactoryBuilder#applyValidatorFactory(Object)
*/
String JAKARTA_VALIDATION_FACTORY = "jakarta.persistence.validation.factory";
/**
* Used to coordinate with bean validators.
* <p>
* See JPA 2 section 8.2.1.9
*/
@SuppressWarnings("unused")
String JAKARTA_PERSIST_VALIDATION_GROUP = "jakarta.persistence.validation.group.pre-persist";
/**
* Used to coordinate with bean validators.
* <p>
* See JPA 2 section 8.2.1.9
*/
@SuppressWarnings("unused")
String JAKARTA_UPDATE_VALIDATION_GROUP = "jakarta.persistence.validation.group.pre-update";
/**
* Used to coordinate with bean validators.
* <p>
* See JPA 2 section 8.2.1.9
*/
@SuppressWarnings("unused")
String JAKARTA_REMOVE_VALIDATION_GROUP = "jakarta.persistence.validation.group.pre-remove";
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Hibernate settings
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* Enable nullability checking, raises an exception if an attribute marked as
* {@linkplain jakarta.persistence.Basic#optional() not null} is null at runtime.
* <p>
* Defaults to disabled if Bean Validation is present in the classpath and
* annotations are used, or enabled otherwise.
*
* @see org.hibernate.boot.SessionFactoryBuilder#applyNullabilityChecking(boolean)
*/
String CHECK_NULLABILITY = "hibernate.check_nullability";
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Legacy JPA settings
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* @deprecated Use {@link #JAKARTA_VALIDATION_MODE} instead
*/
@Deprecated
@SuppressWarnings("DeprecatedIsStillUsed")
String JPA_VALIDATION_MODE = "javax.persistence.validation.mode";
/**
* @deprecated Use {@link #JAKARTA_VALIDATION_FACTORY} instead
*/
@Deprecated
@SuppressWarnings("DeprecatedIsStillUsed")
String JPA_VALIDATION_FACTORY = "javax.persistence.validation.factory";
/**
* @deprecated Use {@link #JAKARTA_PERSIST_VALIDATION_GROUP} instead
*/
@Deprecated
String JPA_PERSIST_VALIDATION_GROUP = "javax.persistence.validation.group.pre-persist";
/**
* @deprecated Use {@link #JAKARTA_UPDATE_VALIDATION_GROUP} instead
*/
@Deprecated
String JPA_UPDATE_VALIDATION_GROUP = "javax.persistence.validation.group.pre-update";
/**
* @deprecated Use {@link #JAKARTA_REMOVE_VALIDATION_GROUP} instead
*/
@Deprecated
String JPA_REMOVE_VALIDATION_GROUP = "javax.persistence.validation.group.pre-remove";
}

View File

@ -11,6 +11,7 @@ import java.util.Map;
import org.hibernate.boot.registry.StandardServiceInitiator; import org.hibernate.boot.registry.StandardServiceInitiator;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.BatchSettings;
import org.hibernate.cfg.Environment; import org.hibernate.cfg.Environment;
import org.hibernate.engine.jdbc.batch.spi.BatchBuilder; import org.hibernate.engine.jdbc.batch.spi.BatchBuilder;
import org.hibernate.internal.util.config.ConfigurationHelper; import org.hibernate.internal.util.config.ConfigurationHelper;
@ -28,13 +29,6 @@ public class BatchBuilderInitiator implements StandardServiceInitiator<BatchBuil
*/ */
public static final BatchBuilderInitiator INSTANCE = new BatchBuilderInitiator(); public static final BatchBuilderInitiator INSTANCE = new BatchBuilderInitiator();
/**
* Names the BatchBuilder implementation to use.
*
* @see AvailableSettings#BATCH_STRATEGY
*/
public static final String BUILDER = "hibernate.jdbc.batch.builder";
@Override @Override
public Class<BatchBuilder> getServiceInitiated() { public Class<BatchBuilder> getServiceInitiated() {
return BatchBuilder.class; return BatchBuilder.class;
@ -42,15 +36,15 @@ public class BatchBuilderInitiator implements StandardServiceInitiator<BatchBuil
@Override @Override
public BatchBuilder initiateService(Map<String, Object> configurationValues, ServiceRegistryImplementor registry) { public BatchBuilder initiateService(Map<String, Object> configurationValues, ServiceRegistryImplementor registry) {
Object builder = configurationValues.get( BUILDER ); Object builder = configurationValues.get( BatchSettings.BUILDER );
if ( builder == null ) { if ( builder == null ) {
builder = configurationValues.get( AvailableSettings.BATCH_STRATEGY ); builder = configurationValues.get( BatchSettings.BATCH_STRATEGY );
} }
if ( builder == null ) { if ( builder == null ) {
return new BatchBuilderImpl( return new BatchBuilderImpl(
ConfigurationHelper.getInt( Environment.STATEMENT_BATCH_SIZE, configurationValues, 1 ) ConfigurationHelper.getInt( BatchSettings.STATEMENT_BATCH_SIZE, configurationValues, 1 )
); );
} }

View File

@ -17,7 +17,7 @@ import org.hibernate.service.Service;
* A builder for {@link Batch} instances. * A builder for {@link Batch} instances.
* <p> * <p>
* A custom {@code BatchBuilder} may be selected using the configuration property * A custom {@code BatchBuilder} may be selected using the configuration property
* {@value org.hibernate.cfg.AvailableSettings#BATCH_STRATEGY}. * {@value org.hibernate.cfg.AvailableSettings#BUILDER}.
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */

View File

@ -20,6 +20,8 @@ import org.hibernate.HibernateException;
import org.hibernate.boot.registry.StandardServiceInitiator; import org.hibernate.boot.registry.StandardServiceInitiator;
import org.hibernate.boot.registry.selector.spi.StrategySelector; import org.hibernate.boot.registry.selector.spi.StrategySelector;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.C3p0Settings;
import org.hibernate.cfg.ProxoolSettings;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
@ -94,7 +96,9 @@ public class ConnectionProviderInitiator implements StandardServiceInitiator<Con
} }
@Override @Override
public ConnectionProvider initiateService(Map<String, Object> configurationValues, ServiceRegistryImplementor registry) { public ConnectionProvider initiateService(
Map<String, Object> configurationValues,
ServiceRegistryImplementor registry) {
if ( isMultiTenancyEnabled( registry ) ) { if ( isMultiTenancyEnabled( registry ) ) {
// nothing to do, but given the separate hierarchies have to handle this here. // nothing to do, but given the separate hierarchies have to handle this here.
return null; return null;
@ -148,7 +152,8 @@ public class ConnectionProviderInitiator implements StandardServiceInitiator<Con
ConnectionProvider connectionProvider = null; ConnectionProvider connectionProvider = null;
final Class<? extends ConnectionProvider> singleRegisteredProvider = getSingleRegisteredProvider( strategySelector ); final Class<? extends ConnectionProvider> singleRegisteredProvider = getSingleRegisteredProvider(
strategySelector );
if ( singleRegisteredProvider != null ) { if ( singleRegisteredProvider != null ) {
try { try {
connectionProvider = singleRegisteredProvider.newInstance(); connectionProvider = singleRegisteredProvider.newInstance();
@ -244,7 +249,7 @@ public class ConnectionProviderInitiator implements StandardServiceInitiator<Con
private static boolean c3p0ConfigDefined(Map<String, Object> configValues) { private static boolean c3p0ConfigDefined(Map<String, Object> configValues) {
for ( String key : configValues.keySet() ) { for ( String key : configValues.keySet() ) {
if ( key.startsWith( AvailableSettings.C3P0_CONFIG_PREFIX ) ) { if ( key.startsWith( C3p0Settings.C3P0_CONFIG_PREFIX + "." ) ) {
return true; return true;
} }
} }
@ -263,7 +268,7 @@ public class ConnectionProviderInitiator implements StandardServiceInitiator<Con
private static boolean proxoolConfigDefined(Map<String, Object> configValues) { private static boolean proxoolConfigDefined(Map<String, Object> configValues) {
for ( String key : configValues.keySet() ) { for ( String key : configValues.keySet() ) {
if ( key.startsWith( AvailableSettings.PROXOOL_CONFIG_PREFIX ) ) { if ( key.startsWith( ProxoolSettings.PROXOOL_CONFIG_PREFIX ) ) {
return true; return true;
} }
} }
@ -503,4 +508,27 @@ public class ConnectionProviderInitiator implements StandardServiceInitiator<Con
} }
return name; return name;
} }
public static String extractSetting(Map<String, Object> settings, String... names) {
for ( int i = 0; i < names.length; i++ ) {
if ( settings.containsKey( names[i] ) ) {
return (String) settings.get( names[i] );
}
}
return null;
}
@FunctionalInterface
public interface SettingConsumer {
void consumeSetting(String name, String value);
}
public static void consumeSetting(Map<String, Object> settings, SettingConsumer consumer, String... names) {
for ( int i = 0; i < names.length; i++ ) {
if ( settings.containsKey( names[i] ) ) {
consumer.consumeSetting( names[i], (String) settings.get( names[i] ) );
return;
}
}
}
} }

View File

@ -13,12 +13,15 @@ import javax.sql.DataSource;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.MultiTenancySettings;
import org.hibernate.engine.config.spi.ConfigurationService; import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.jndi.spi.JndiService; import org.hibernate.engine.jndi.spi.JndiService;
import org.hibernate.service.spi.ServiceRegistryAwareService; import org.hibernate.service.spi.ServiceRegistryAwareService;
import org.hibernate.service.spi.ServiceRegistryImplementor; import org.hibernate.service.spi.ServiceRegistryImplementor;
import org.hibernate.service.spi.Stoppable; import org.hibernate.service.spi.Stoppable;
import static org.hibernate.cfg.MultiTenancySettings.TENANT_IDENTIFIER_TO_USE_FOR_ANY_KEY;
/** /**
* A concrete implementation of the {@link MultiTenantConnectionProvider} contract bases on a number of * A concrete implementation of the {@link MultiTenantConnectionProvider} contract bases on a number of
* reasonable assumptions. We assume that:<ul> * reasonable assumptions. We assume that:<ul>
@ -28,7 +31,7 @@ import org.hibernate.service.spi.Stoppable;
* </li> * </li>
* <li> * <li>
* {@value AvailableSettings#DATASOURCE} is a string naming either the {@literal any} * {@value AvailableSettings#DATASOURCE} is a string naming either the {@literal any}
* data source or the base JNDI context. If the latter, {@link #TENANT_IDENTIFIER_TO_USE_FOR_ANY_KEY} must * data source or the base JNDI context. If the latter, {@link MultiTenancySettings#TENANT_IDENTIFIER_TO_USE_FOR_ANY_KEY} must
* also be set. * also be set.
* </li> * </li>
* </ul> * </ul>
@ -39,11 +42,6 @@ public class DataSourceBasedMultiTenantConnectionProviderImpl
extends AbstractDataSourceBasedMultiTenantConnectionProviderImpl extends AbstractDataSourceBasedMultiTenantConnectionProviderImpl
implements ServiceRegistryAwareService, Stoppable { implements ServiceRegistryAwareService, Stoppable {
/**
* Identifies the DataSource name to use for {@link #selectAnyDataSource} handling
*/
public static final String TENANT_IDENTIFIER_TO_USE_FOR_ANY_KEY = "hibernate.multi_tenant.datasource.identifier_for_any";
private Map<String,DataSource> dataSourceMap; private Map<String,DataSource> dataSourceMap;
private JndiService jndiService; private JndiService jndiService;
private String tenantIdentifierForAny; private String tenantIdentifierForAny;

View File

@ -71,8 +71,8 @@ public interface ConnectionPoolingLogger extends BasicLogger {
void usingUrl(String url); void usingUrl(String url);
@LogMessage(level = WARN) @LogMessage(level = WARN)
@Message(value = "No JDBC Driver class was specified by property %s", id = 10001006) @Message(id = 10001006, value = "No JDBC Driver class was specified by property `jakarta.persistence.jdbc.driver`, `hibernate.driver` or `javax.persistence.jdbc.driver`")
void jdbcDriverNotSpecified(String driver); void jdbcDriverNotSpecified();
@LogMessage(level = INFO) @LogMessage(level = INFO)
@Message(value = "JDBC isolation level: %s", id = 10001007) @Message(value = "JDBC isolation level: %s", id = 10001007)

View File

@ -122,6 +122,9 @@ import static org.hibernate.cfg.AvailableSettings.SESSION_FACTORY_NAME;
import static org.hibernate.cfg.AvailableSettings.TRANSACTION_COORDINATOR_STRATEGY; import static org.hibernate.cfg.AvailableSettings.TRANSACTION_COORDINATOR_STRATEGY;
import static org.hibernate.cfg.AvailableSettings.URL; import static org.hibernate.cfg.AvailableSettings.URL;
import static org.hibernate.cfg.AvailableSettings.USER; import static org.hibernate.cfg.AvailableSettings.USER;
import static org.hibernate.cfg.BytecodeSettings.ENHANCER_ENABLE_ASSOCIATION_MANAGEMENT;
import static org.hibernate.cfg.BytecodeSettings.ENHANCER_ENABLE_DIRTY_TRACKING;
import static org.hibernate.cfg.BytecodeSettings.ENHANCER_ENABLE_LAZY_INITIALIZATION;
import static org.hibernate.internal.HEMLogging.messageLogger; import static org.hibernate.internal.HEMLogging.messageLogger;
import static org.hibernate.internal.log.DeprecationLogger.DEPRECATION_LOGGER; import static org.hibernate.internal.log.DeprecationLogger.DEPRECATION_LOGGER;
@ -305,7 +308,7 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
// container situations, calling back into PersistenceUnitInfo#addClassTransformer // container situations, calling back into PersistenceUnitInfo#addClassTransformer
final boolean dirtyTrackingEnabled; final boolean dirtyTrackingEnabled;
Object propertyValue = configurationValues.remove( AvailableSettings.ENHANCER_ENABLE_DIRTY_TRACKING ); Object propertyValue = configurationValues.remove( ENHANCER_ENABLE_DIRTY_TRACKING );
if ( propertyValue != null ) { if ( propertyValue != null ) {
dirtyTrackingEnabled = Boolean.parseBoolean( propertyValue.toString() ); dirtyTrackingEnabled = Boolean.parseBoolean( propertyValue.toString() );
} }
@ -313,19 +316,19 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
dirtyTrackingEnabled = true; dirtyTrackingEnabled = true;
} }
final boolean lazyInitializationEnabled; final boolean lazyInitializationEnabled;
propertyValue = configurationValues.remove( AvailableSettings.ENHANCER_ENABLE_LAZY_INITIALIZATION ); propertyValue = configurationValues.remove( ENHANCER_ENABLE_LAZY_INITIALIZATION );
if ( propertyValue != null ) { if ( propertyValue != null ) {
lazyInitializationEnabled = Boolean.parseBoolean( propertyValue.toString() ); lazyInitializationEnabled = Boolean.parseBoolean( propertyValue.toString() );
} }
else { else {
lazyInitializationEnabled = true; lazyInitializationEnabled = true;
} }
final boolean associationManagementEnabled = readBooleanConfigurationValue( AvailableSettings.ENHANCER_ENABLE_ASSOCIATION_MANAGEMENT ); final boolean associationManagementEnabled = readBooleanConfigurationValue( ENHANCER_ENABLE_ASSOCIATION_MANAGEMENT );
if ( !lazyInitializationEnabled ) { if ( !lazyInitializationEnabled ) {
DEPRECATION_LOGGER.deprecatedSettingForRemoval( AvailableSettings.ENHANCER_ENABLE_LAZY_INITIALIZATION, "true" ); DEPRECATION_LOGGER.deprecatedSettingForRemoval( ENHANCER_ENABLE_LAZY_INITIALIZATION, "true" );
} }
if ( !dirtyTrackingEnabled ) { if ( !dirtyTrackingEnabled ) {
DEPRECATION_LOGGER.deprecatedSettingForRemoval( AvailableSettings.ENHANCER_ENABLE_DIRTY_TRACKING, "true" ); DEPRECATION_LOGGER.deprecatedSettingForRemoval( ENHANCER_ENABLE_DIRTY_TRACKING, "true" );
} }
if ( dirtyTrackingEnabled || lazyInitializationEnabled || associationManagementEnabled ) { if ( dirtyTrackingEnabled || lazyInitializationEnabled || associationManagementEnabled ) {

View File

@ -22,6 +22,8 @@ import org.jboss.logging.Logger;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
import static org.hibernate.cfg.StatisticsSettings.STATS_BUILDER;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
@ -30,12 +32,6 @@ public class StatisticsInitiator implements SessionFactoryServiceInitiator<Stati
public static final StatisticsInitiator INSTANCE = new StatisticsInitiator(); public static final StatisticsInitiator INSTANCE = new StatisticsInitiator();
/**
* Names the {@link StatisticsFactory} to use. Recognizes both a class name as well as an instance of
* {@link StatisticsFactory}.
*/
public static final String STATS_BUILDER = "hibernate.stats.factory";
@Override @Override
public Class<StatisticsImplementor> getServiceInitiated() { public Class<StatisticsImplementor> getServiceInitiated() {
return StatisticsImplementor.class; return StatisticsImplementor.class;

View File

@ -9,6 +9,7 @@ package org.hibernate.orm.test.insertordering;
import java.util.Iterator; import java.util.Iterator;
import java.util.function.Supplier; import java.util.function.Supplier;
import org.hibernate.cfg.BatchSettings;
import org.hibernate.cfg.Environment; import org.hibernate.cfg.Environment;
import org.hibernate.engine.jdbc.batch.internal.BatchBuilderInitiator; import org.hibernate.engine.jdbc.batch.internal.BatchBuilderInitiator;
import org.hibernate.engine.jdbc.batch.internal.BatchImpl; import org.hibernate.engine.jdbc.batch.internal.BatchImpl;
@ -35,9 +36,9 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
) )
@SessionFactory @SessionFactory
@ServiceRegistry( @ServiceRegistry(
settings = {@Setting( name = Environment.ORDER_INSERTS, value = "true"), settings = {@Setting( name = BatchSettings.ORDER_INSERTS, value = "true"),
@Setting( name = Environment.STATEMENT_BATCH_SIZE, value = "10"), @Setting( name = BatchSettings.STATEMENT_BATCH_SIZE, value = "10"),
@Setting( name = BatchBuilderInitiator.BUILDER, value = "org.hibernate.orm.test.insertordering.InsertOrderingTest$StatsBatchBuilder" ) @Setting( name = BatchSettings.BUILDER, value = "org.hibernate.orm.test.insertordering.InsertOrderingTest$StatsBatchBuilder" )
} }
) )
public class InsertOrderingTest { public class InsertOrderingTest {

View File

@ -6,8 +6,7 @@
*/ */
package org.hibernate.orm.test.jpa.transaction.batch; package org.hibernate.orm.test.jpa.transaction.batch;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.BatchSettings;
import org.hibernate.engine.jdbc.batch.internal.BatchBuilderInitiator;
import org.hibernate.testing.TestForIssue; import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope; import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
@ -30,11 +29,11 @@ import static org.assertj.core.api.Assertions.assertThat;
FailingAddToBatchTest.MyEntity.class FailingAddToBatchTest.MyEntity.class
}, },
integrationSettings = { integrationSettings = {
@Setting(name = AvailableSettings.STATEMENT_BATCH_SIZE, value = "50") @Setting(name = BatchSettings.STATEMENT_BATCH_SIZE, value = "50")
}, },
settingProviders = { settingProviders = {
@SettingProvider( @SettingProvider(
settingName = BatchBuilderInitiator.BUILDER, settingName = BatchSettings.BUILDER,
provider = AbstractBatchingTest.ErrorBatch2BuilderSettingProvider.class provider = AbstractBatchingTest.ErrorBatch2BuilderSettingProvider.class
) )
} }

View File

@ -7,7 +7,7 @@
package org.hibernate.orm.test.jpa.transaction.batch; package org.hibernate.orm.test.jpa.transaction.batch;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.jdbc.batch.internal.BatchBuilderInitiator; import org.hibernate.cfg.BatchSettings;
import org.hibernate.orm.test.jpa.transaction.JtaPlatformSettingProvider; import org.hibernate.orm.test.jpa.transaction.JtaPlatformSettingProvider;
import org.hibernate.testing.TestForIssue; import org.hibernate.testing.TestForIssue;
@ -53,7 +53,7 @@ import static org.junit.jupiter.api.Assertions.fail;
provider = JtaPlatformSettingProvider.class provider = JtaPlatformSettingProvider.class
), ),
@SettingProvider( @SettingProvider(
settingName = BatchBuilderInitiator.BUILDER, settingName = BatchSettings.BUILDER,
provider = AbstractBatchingTest.ErrorBatch2BuilderSettingProvider.class provider = AbstractBatchingTest.ErrorBatch2BuilderSettingProvider.class
) )
} }

View File

@ -7,7 +7,7 @@
package org.hibernate.orm.test.jpa.transaction.batch; package org.hibernate.orm.test.jpa.transaction.batch;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.jdbc.batch.internal.BatchBuilderInitiator; import org.hibernate.cfg.BatchSettings;
import org.hibernate.orm.test.jpa.transaction.JtaPlatformSettingProvider; import org.hibernate.orm.test.jpa.transaction.JtaPlatformSettingProvider;
import org.hibernate.testing.TestForIssue; import org.hibernate.testing.TestForIssue;
@ -54,7 +54,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
provider = JtaPlatformSettingProvider.class provider = JtaPlatformSettingProvider.class
), ),
@SettingProvider( @SettingProvider(
settingName = BatchBuilderInitiator.BUILDER, settingName = BatchSettings.BUILDER,
provider = AbstractBatchingTest.Batch2BuilderSettingProvider.class provider = AbstractBatchingTest.Batch2BuilderSettingProvider.class
) )
} }

View File

@ -11,10 +11,13 @@ import java.util.Map;
import java.util.Properties; import java.util.Properties;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.JdbcSettings;
import org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator; import org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator;
import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariConfig;
import static org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator.consumeSetting;
/** /**
* Utility class to map Hibernate properties to HikariCP configuration properties. * Utility class to map Hibernate properties to HikariCP configuration properties.
* *
@ -33,12 +36,43 @@ public class HikariConfigurationUtil {
*/ */
public static HikariConfig loadConfiguration(Map<String,Object> props) { public static HikariConfig loadConfiguration(Map<String,Object> props) {
Properties hikariProps = new Properties(); Properties hikariProps = new Properties();
copyProperty( AvailableSettings.AUTOCOMMIT, props, "autoCommit", hikariProps ); copyProperty( JdbcSettings.AUTOCOMMIT, props, "autoCommit", hikariProps );
copyProperty( AvailableSettings.DRIVER, props, "driverClassName", hikariProps ); copyProperty(
copyProperty( AvailableSettings.URL, props, "jdbcUrl", hikariProps ); props,
copyProperty( AvailableSettings.USER, props, "username", hikariProps ); "driverClassName",
copyProperty( AvailableSettings.PASS, props, "password", hikariProps ); hikariProps,
JdbcSettings.JAKARTA_JDBC_DRIVER,
JdbcSettings.DRIVER,
JdbcSettings.JPA_JDBC_DRIVER
);
copyProperty(
props,
"jdbcUrl",
hikariProps,
JdbcSettings.JAKARTA_JDBC_URL,
JdbcSettings.URL,
JdbcSettings.JPA_JDBC_URL
);
copyProperty(
props,
"username",
hikariProps,
JdbcSettings.JAKARTA_JDBC_USER,
JdbcSettings.USER,
JdbcSettings.JPA_JDBC_USER
);
copyProperty(
props,
"password",
hikariProps,
AvailableSettings.JAKARTA_JDBC_PASSWORD,
AvailableSettings.PASS,
AvailableSettings.JPA_JDBC_PASSWORD
);
copyIsolationSetting( props, hikariProps ); copyIsolationSetting( props, hikariProps );
@ -57,6 +91,14 @@ public class HikariConfigurationUtil {
} }
} }
private static void copyProperty(Map<String,Object> src, String dstKey, Properties dst, String... srcKeys) {
consumeSetting(
src,
(name, value) -> dst.setProperty( dstKey, value ),
srcKeys
);
}
private static void copyIsolationSetting(Map<String,Object> props, Properties hikariProps) { private static void copyIsolationSetting(Map<String,Object> props, Properties hikariProps) {
final Integer isolation = ConnectionProviderInitiator.extractIsolation( props ); final Integer isolation = ConnectionProviderInitiator.extractIsolation( props );
if ( isolation != null ) { if ( isolation != null ) {

View File

@ -17,7 +17,8 @@ import java.util.Properties;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.cfg.Environment; import org.hibernate.cfg.JdbcSettings;
import org.hibernate.cfg.ProxoolSettings;
import org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator; import org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
@ -110,19 +111,19 @@ public class ProxoolConnectionProvider
@Override @Override
public void configure(Map<String, Object> props) { public void configure(Map<String, Object> props) {
// Get the configurator files (if available) // Get the configurator files (if available)
final String jaxpFile = (String) props.get( Environment.PROXOOL_XML ); final String jaxpFile = (String) props.get( ProxoolSettings.PROXOOL_XML );
final String propFile = (String) props.get( Environment.PROXOOL_PROPERTIES ); final String propFile = (String) props.get( ProxoolSettings.PROXOOL_PROPERTIES );
final String externalConfig = (String) props.get( Environment.PROXOOL_EXISTING_POOL ); final String externalConfig = (String) props.get( ProxoolSettings.PROXOOL_EXISTING_POOL );
// Default the Proxool alias setting // Default the Proxool alias setting
proxoolAlias = (String) props.get( Environment.PROXOOL_POOL_ALIAS ); proxoolAlias = (String) props.get( ProxoolSettings.PROXOOL_POOL_ALIAS );
// Configured outside of Hibernate (i.e. Servlet container, or Java Bean Container // Configured outside of Hibernate (i.e. Servlet container, or Java Bean Container
// already has Proxool pools running, and this provider is to just borrow one of these // already has Proxool pools running, and this provider is to just borrow one of these
if ( "true".equals( externalConfig ) ) { if ( "true".equals( externalConfig ) ) {
// Validate that an alias name was provided to determine which pool to use // Validate that an alias name was provided to determine which pool to use
if ( !StringHelper.isNotEmpty( proxoolAlias ) ) { if ( !StringHelper.isNotEmpty( proxoolAlias ) ) {
final String msg = PROXOOL_MESSAGE_LOGGER.unableToConfigureProxoolProviderToUseExistingInMemoryPool( Environment.PROXOOL_POOL_ALIAS ); final String msg = PROXOOL_MESSAGE_LOGGER.unableToConfigureProxoolProviderToUseExistingInMemoryPool( ProxoolSettings.PROXOOL_POOL_ALIAS );
PROXOOL_LOGGER.error( msg ); PROXOOL_LOGGER.error( msg );
throw new HibernateException( msg ); throw new HibernateException( msg );
} }
@ -141,7 +142,7 @@ public class ProxoolConnectionProvider
// Validate that an alias name was provided to determine which pool to use // Validate that an alias name was provided to determine which pool to use
if ( !StringHelper.isNotEmpty( proxoolAlias ) ) { if ( !StringHelper.isNotEmpty( proxoolAlias ) ) {
final String msg = PROXOOL_MESSAGE_LOGGER.unableToConfigureProxoolProviderToUseJaxp( Environment.PROXOOL_POOL_ALIAS ); final String msg = PROXOOL_MESSAGE_LOGGER.unableToConfigureProxoolProviderToUseJaxp( ProxoolSettings.PROXOOL_POOL_ALIAS );
PROXOOL_LOGGER.error( msg ); PROXOOL_LOGGER.error( msg );
throw new HibernateException( msg ); throw new HibernateException( msg );
} }
@ -166,7 +167,7 @@ public class ProxoolConnectionProvider
// Validate that an alias name was provided to determine which pool to use // Validate that an alias name was provided to determine which pool to use
if ( !StringHelper.isNotEmpty( proxoolAlias ) ) { if ( !StringHelper.isNotEmpty( proxoolAlias ) ) {
final String msg = PROXOOL_MESSAGE_LOGGER.unableToConfigureProxoolProviderToUsePropertiesFile( Environment.PROXOOL_POOL_ALIAS ); final String msg = PROXOOL_MESSAGE_LOGGER.unableToConfigureProxoolProviderToUsePropertiesFile( ProxoolSettings.PROXOOL_POOL_ALIAS );
PROXOOL_LOGGER.error( msg ); PROXOOL_LOGGER.error( msg );
throw new HibernateException( msg ); throw new HibernateException( msg );
} }
@ -189,7 +190,7 @@ public class ProxoolConnectionProvider
isolation = ConnectionProviderInitiator.extractIsolation( props ); isolation = ConnectionProviderInitiator.extractIsolation( props );
PROXOOL_MESSAGE_LOGGER.jdbcIsolationLevel( ConnectionProviderInitiator.toIsolationNiceName( isolation ) ); PROXOOL_MESSAGE_LOGGER.jdbcIsolationLevel( ConnectionProviderInitiator.toIsolationNiceName( isolation ) );
autocommit = ConfigurationHelper.getBoolean( Environment.AUTOCOMMIT, props ); autocommit = ConfigurationHelper.getBoolean( JdbcSettings.AUTOCOMMIT, props );
PROXOOL_MESSAGE_LOGGER.autoCommitMode( autocommit ); PROXOOL_MESSAGE_LOGGER.autoCommitMode( autocommit );
} }

View File

@ -1,5 +1,7 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

View File

@ -1,7 +1,7 @@
#!/usr/bin/env sh #!/bin/sh
# #
# Copyright 2015 the original author or authors. # Copyright © 2015-2021 the original authors.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@ -17,67 +17,98 @@
# #
############################################################################## ##############################################################################
## #
## Gradle start up script for UN*X # Gradle start up script for POSIX generated by Gradle.
## #
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
############################################################################## ##############################################################################
# Attempt to set APP_HOME # Attempt to set APP_HOME
# Resolve links: $0 may be a link # Resolve links: $0 may be a link
PRG="$0" app_path=$0
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do # Need this for daisy-chained symlinks.
ls=`ls -ld "$PRG"` while
link=`expr "$ls" : '.*-> \(.*\)$'` APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
if expr "$link" : '/.*' > /dev/null; then [ -h "$app_path" ]
PRG="$link" do
else ls=$( ls -ld "$app_path" )
PRG=`dirname "$PRG"`"/$link" link=${ls#*' -> '}
fi case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle" # This is normally unused
APP_BASE_NAME=`basename "$0"` # shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value. # Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum" MAX_FD=maximum
warn () { warn () {
echo "$*" echo "$*"
} } >&2
die () { die () {
echo echo
echo "$*" echo "$*"
echo echo
exit 1 exit 1
} } >&2
# OS specific support (must be 'true' or 'false'). # OS specific support (must be 'true' or 'false').
cygwin=false cygwin=false
msys=false msys=false
darwin=false darwin=false
nonstop=false nonstop=false
case "`uname`" in case "$( uname )" in #(
CYGWIN* ) CYGWIN* ) cygwin=true ;; #(
cygwin=true Darwin* ) darwin=true ;; #(
;; MSYS* | MINGW* ) msys=true ;; #(
Darwin* ) NONSTOP* ) nonstop=true ;;
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
@ -87,9 +118,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
if [ -n "$JAVA_HOME" ] ; then if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables # IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java" JAVACMD=$JAVA_HOME/jre/sh/java
else else
JAVACMD="$JAVA_HOME/bin/java" JAVACMD=$JAVA_HOME/bin/java
fi fi
if [ ! -x "$JAVACMD" ] ; then if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
@ -98,88 +129,120 @@ Please set the JAVA_HOME variable in your environment to match the
location of your Java installation." location of your Java installation."
fi fi
else else
JAVACMD="java" JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the Please set the JAVA_HOME variable in your environment to match the
location of your Java installation." location of your Java installation."
fi fi
fi
# Increase the maximum file descriptors if we can. # Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
MAX_FD_LIMIT=`ulimit -H -n` case $MAX_FD in #(
if [ $? -eq 0 ] ; then max*)
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
MAX_FD="$MAX_FD_LIMIT" # shellcheck disable=SC3045
fi MAX_FD=$( ulimit -H -n ) ||
ulimit -n $MAX_FD warn "Could not query maximum file descriptor limit"
if [ $? -ne 0 ] ; then esac
warn "Could not set maximum file descriptor limit: $MAX_FD" case $MAX_FD in #(
fi '' | soft) :;; #(
else *)
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
fi # shellcheck disable=SC3045
fi ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac esac
fi fi
# Escape application args # Collect all arguments for the java command, stacking in reverse order:
save () { # * args from the command line
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done # * the main class name
echo " " # * -classpath
} # * -D...appname settings
APP_ARGS=`save "$@"` # * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# Collect all arguments for the java command, following the shell quoting and substitution rules # For Cygwin or MSYS, switch paths to Windows format before running java
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@" exec "$JAVACMD" "$@"

View File

@ -26,6 +26,7 @@ if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0 set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=. if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0 set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME% set APP_HOME=%DIRNAME%
@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1 %JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute if %ERRORLEVEL% equ 0 goto execute
echo. echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
:end :end
@rem End local scope for the variables with windows NT shell @rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd if %ERRORLEVEL% equ 0 goto mainEnd
:fail :fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code! rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 set EXIT_CODE=%ERRORLEVEL%
exit /b 1 if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd :mainEnd
if "%OS%"=="Windows_NT" endlocal if "%OS%"=="Windows_NT" endlocal

View File

@ -12,8 +12,8 @@ import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.Writer; import java.io.Writer;
import java.nio.file.Files; import java.nio.file.Files;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.SortedMap;
import java.util.SortedSet; import java.util.SortedSet;
import org.gradle.api.Project; import org.gradle.api.Project;
@ -23,11 +23,10 @@ import org.gradle.api.file.RegularFile;
* @author Marko Bekhta * @author Marko Bekhta
*/ */
public class AsciiDocWriter { public class AsciiDocWriter {
public static final String ANCHOR_BASE = "settings-";
public static final String ANCHOR_START = "[[" + ANCHOR_BASE;
public static void writeToFile( public static void writeToFile(
SortedMap<SettingsDocSection, SortedSet<SettingDescriptor>> settingDescriptorMap, String anchorNameBase,
Map<SettingsDocSection, SortedSet<SettingDescriptor>> settingDescriptorMap,
RegularFile outputFile, RegularFile outputFile,
Project project) { Project project) {
final File outputFileAsFile = outputFile.getAsFile(); final File outputFileAsFile = outputFile.getAsFile();
@ -39,7 +38,7 @@ public class AsciiDocWriter {
} }
try ( FileWriter fileWriter = new FileWriter( outputFileAsFile ) ) { try ( FileWriter fileWriter = new FileWriter( outputFileAsFile ) ) {
write( settingDescriptorMap, fileWriter, project ); write( anchorNameBase, settingDescriptorMap, fileWriter, project );
} }
catch (IOException e) { catch (IOException e) {
throw new RuntimeException( "Failed to produce asciidoc output for collected properties", e ); throw new RuntimeException( "Failed to produce asciidoc output for collected properties", e );
@ -47,30 +46,35 @@ public class AsciiDocWriter {
} }
private static void write( private static void write(
SortedMap<SettingsDocSection, SortedSet<SettingDescriptor>> settingDescriptorMap, String anchorNameBase,
Map<SettingsDocSection, SortedSet<SettingDescriptor>> settingDescriptorMap,
FileWriter writer, FileWriter writer,
Project project) throws IOException { Project project) throws IOException {
for ( Map.Entry<SettingsDocSection, SortedSet<SettingDescriptor>> entry : settingDescriptorMap.entrySet() ) { for ( Map.Entry<SettingsDocSection, SortedSet<SettingDescriptor>> entry : settingDescriptorMap.entrySet() ) {
final SettingsDocSection sectionDescriptor = entry.getKey(); final SettingsDocSection sectionDescriptor = entry.getKey();
final SortedSet<SettingDescriptor> sectionSettingDescriptors = entry.getValue(); final SortedSet<SettingDescriptor> sectionSettingDescriptors = entry.getValue();
if ( sectionSettingDescriptors.isEmpty() ) {
continue;
}
final Project sourceProject = project.getRootProject().project( sectionDescriptor.getProjectPath() ); final String sectionName = sectionDescriptor.getName();
// write an anchor in the form `[[settings-{moduleName}]]`, e.g. `[[settings-hibernate-core]]` // write an anchor in the form `[[{anchorNameBase}-{sectionName}]]`
tryToWriteLine( writer, ANCHOR_START, sourceProject.getName(), "]]" ); tryToWriteLine( writer, "[[", anchorNameBase, "-", sectionName, "]]" );
tryToWriteLine( writer, "=== ", "(", sourceProject.getName(), ") ", sourceProject.getDescription() ); tryToWriteLine( writer, "=== ", sectionDescriptor.getSummary() );
writer.write( '\n' ); writer.write( '\n' );
for ( SettingDescriptor settingDescriptor : sectionSettingDescriptors ) { for ( SettingDescriptor settingDescriptor : sectionSettingDescriptors ) {
writeSettingAnchor( settingDescriptor, writer ); // write an anchor in the form `[[{anchorNameBase}-{settingName}]]`
tryToWriteLine( writer, "[[", anchorNameBase, "-", settingDescriptor.getName(), "]]" );
writeSettingName( settingDescriptor, writer ); writeSettingName( settingDescriptor, writer );
writer.write( "::\n" ); writer.write( "::\n" );
writeLifecycleNotes( settingDescriptor, writer ); writeMetadata( settingDescriptor, writer );
writer.write( settingDescriptor.getJavadoc() ); writer.write( settingDescriptor.getComment() );
writer.write( "\n\n'''\n" ); writer.write( "\n\n'''\n" );
} }
@ -79,19 +83,54 @@ public class AsciiDocWriter {
} }
} }
private static void writeLifecycleNotes(SettingDescriptor settingDescriptor, FileWriter writer) throws IOException { private static void writeMetadata(SettingDescriptor settingDescriptor, FileWriter writer) throws IOException {
// NOTE : at the moment, there is at least one setting that is both which fundamentally seems wrong if ( !settingDescriptor.hasMetadata() ) {
if ( settingDescriptor.isIncubating() ) { return;
writer.write( "NOTE:: _This setting is considered incubating_\n\n" );
} }
if ( settingDescriptor.isDeprecated() ) {
writer.write( "WARN:: _This setting is considered deprecated_\n\n" ); writer.write( "+\n" );
writer.write( "****\n" );
writer.write(
String.format(
Locale.ROOT,
"**See:** %s[%s.%s]\n\n",
settingDescriptor.getPublishedJavadocLink(),
Utils.withoutPackagePrefix( settingDescriptor.getSettingsClassName() ),
settingDescriptor.getSettingFieldName()
)
);
// NOTE : Asciidoctor requires that italic always be the innermost formatting
final SettingDescriptor.LifecycleDetails lifecycleDetails = settingDescriptor.getLifecycleDetails();
// NOTE : at the moment, there is at least one setting that is incubating AND deprecated which fundamentally seems wrong
if ( lifecycleDetails.isIncubating() ) {
writer.write( "NOTE: *_This setting is considered incubating_*\n\n" );
} }
if ( lifecycleDetails.isDeprecated() ) {
writer.write( "WARNING: *_This setting is considered deprecated_*\n\n" );
}
if ( lifecycleDetails.getSince() != null ) {
writer.write( "*_Since:_* _" + lifecycleDetails.getSince() + "_\n\n" );
}
if ( settingDescriptor.getDefaultValue() != null ) {
writer.write( "*_Default Value:_* " + settingDescriptor.getDefaultValue() + "\n\n" );
}
if ( settingDescriptor.getApiNote() != null ) {
writer.write( settingDescriptor.getApiNote() + "\n\n" );
}
writer.write( "****\n+\n" );
} }
private static void writeSettingName(SettingDescriptor settingDescriptor, FileWriter writer) throws IOException { private static void writeSettingName(SettingDescriptor settingDescriptor, FileWriter writer) throws IOException {
writer.write( "`" ); writer.write( "`" );
if ( settingDescriptor.isDeprecated() ) { if ( settingDescriptor.getLifecycleDetails().isDeprecated() ) {
writer.write( "[.line-through]#" ); writer.write( "[.line-through]#" );
} }
else { else {
@ -100,7 +139,7 @@ public class AsciiDocWriter {
writer.write( settingDescriptor.getName() ); writer.write( settingDescriptor.getName() );
if ( settingDescriptor.isDeprecated() ) { if ( settingDescriptor.getLifecycleDetails().isDeprecated() ) {
writer.write( '#' ); writer.write( '#' );
} }
else { else {
@ -109,12 +148,6 @@ public class AsciiDocWriter {
writer.write( '`' ); writer.write( '`' );
} }
private static void writeSettingAnchor(SettingDescriptor settingDescriptor, Writer writer) throws IOException {
writer.write( ANCHOR_START );
writer.write( settingDescriptor.getName() );
writer.write( "]] " );
}
private static void tryToWriteLine(Writer writer, String prefix, String value, String... other) { private static void tryToWriteLine(Writer writer, String prefix, String value, String... other) {
try { try {
writer.write( prefix ); writer.write( prefix );

View File

@ -6,36 +6,58 @@
*/ */
package org.hibernate.orm.properties; package org.hibernate.orm.properties;
import java.util.Comparator;
import static java.util.Comparator.comparing;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class SettingDescriptor { public class SettingDescriptor {
public static final Comparator<SettingDescriptor> BY_NAME = comparing( SettingDescriptor::getName );
private final String name; private final String name;
private final String settingsClassName; private final String settingsClassName;
private final String settingFieldName; private final String settingFieldName;
private final String javadoc; private final String publishedJavadocLink;
private final boolean deprecated; private final String comment;
private final boolean incubating; private final String defaultValue;
private final String apiNote;
private final LifecycleDetails lifecycleDetails;
public SettingDescriptor( public SettingDescriptor(
String name, String name,
String settingsClassName, String settingsClassName,
String settingFieldName, String settingFieldName,
String javadoc, String publishedJavadocLink,
boolean deprecated, String comment,
boolean incubating) { String defaultValue,
String apiNote,
LifecycleDetails lifecycleDetails) {
this.name = name; this.name = name;
this.settingsClassName = settingsClassName; this.settingsClassName = settingsClassName;
this.settingFieldName = settingFieldName; this.settingFieldName = settingFieldName;
this.javadoc = javadoc; this.comment = comment;
this.deprecated = deprecated; this.publishedJavadocLink = publishedJavadocLink;
this.incubating = incubating; this.defaultValue = defaultValue;
this.apiNote = apiNote;
this.lifecycleDetails = lifecycleDetails;
}
public SettingDescriptor(
String name,
String settingsClassName,
String settingFieldName,
String publishedJavadocLink,
String comment,
String defaultValue,
String apiNote,
String since,
boolean deprecated,
boolean incubating) {
this(
name,
settingsClassName,
settingFieldName,
publishedJavadocLink, comment,
defaultValue,
apiNote,
new LifecycleDetails( since, deprecated, incubating )
);
} }
/** /**
@ -48,8 +70,26 @@ public class SettingDescriptor {
/** /**
* The Javadoc content * The Javadoc content
*/ */
public String getJavadoc() { public String getComment() {
return javadoc; return comment;
}
public String getPublishedJavadocLink() {
return publishedJavadocLink;
}
/**
* The setting's default value
*/
public String getDefaultValue() {
return defaultValue;
}
/**
* {@code @apiNote} defined on the setting field
*/
public String getApiNote() {
return apiNote;
} }
public String getSettingsClassName() { public String getSettingsClassName() {
@ -60,6 +100,45 @@ public class SettingDescriptor {
return settingFieldName; return settingFieldName;
} }
public LifecycleDetails getLifecycleDetails() {
return lifecycleDetails;
}
public boolean hasMetadata() {
return defaultValue != null
|| apiNote != null
|| lifecycleDetails.since != null
|| lifecycleDetails.incubating
|| lifecycleDetails.deprecated;
}
@Override
public String toString() {
return "setting(" + name + ") {\n" +
" settingsClassName = `" + settingsClassName + "`,\n" +
" settingFieldName = `" + settingFieldName + "`,\n" +
" lifecycle = " + lifecycleDetails + ",\n" +
" defaultValue = `" + defaultValue + "`,\n" +
" apiNote = `" + apiNote + "`,\n" +
" javadoc = ```\n" + comment + "\n```\n" +
"}";
}
public static class LifecycleDetails {
private final String since;
private final boolean incubating;
private final boolean deprecated;
public LifecycleDetails(String since, boolean deprecated, boolean incubating) {
this.since = since;
this.deprecated = deprecated;
this.incubating = incubating;
}
public String getSince() {
return since;
}
public boolean isDeprecated() { public boolean isDeprecated() {
return deprecated; return deprecated;
} }
@ -67,4 +146,14 @@ public class SettingDescriptor {
public boolean isIncubating() { public boolean isIncubating() {
return incubating; return incubating;
} }
@Override
public String toString() {
return "{\n" +
" since = `" + since + "`,\n" +
" incubating = `" + incubating + "`,\n" +
" deprecated = `" + deprecated + "`\n" +
" }";
}
}
} }

View File

@ -0,0 +1,56 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.orm.properties;
import java.util.Comparator;
/**
* Sorts {@link SettingDescriptor} references by setting name with the following precedence - <ol>
* <li>starts with {@code jakarta.persistence.}</li>
* <li>starts with {@code hibernate.}</li>
* <li>starts with {@code javax.persistence.}</li>
* <li>any others (should be none)</li>
* </ol>
*
* @author Steve Ebersole
*/
public class SettingDescriptorComparator implements Comparator<SettingDescriptor> {
public static final SettingDescriptorComparator INSTANCE = new SettingDescriptorComparator();
public static final String JPA_PREFIX = "jakarta.persistence.";
public static final String HIBERNATE_PREFIX = "hibernate.";
public static final String LEGACY_JPA_PREFIX = "javax.persistence.";
@Override
public int compare(SettingDescriptor o1, SettingDescriptor o2) {
if ( o1.getName().startsWith( JPA_PREFIX ) ) {
if ( o2.getName().startsWith( JPA_PREFIX ) ) {
return o1.getName().compareTo( o2.getName() );
}
return -1;
}
if ( o1.getName().startsWith( HIBERNATE_PREFIX ) ) {
if ( o2.getName().startsWith( JPA_PREFIX ) ) {
return 1;
}
if ( o2.getName().startsWith( HIBERNATE_PREFIX ) ) {
return o1.getName().compareTo( o2.getName() );
}
return -1;
}
assert o1.getName().startsWith( LEGACY_JPA_PREFIX );
if ( o2.getName().startsWith( JPA_PREFIX )
|| o2.getName().startsWith( HIBERNATE_PREFIX ) ) {
return 1;
}
return o1.getName().compareTo( o2.getName() );
}
}

View File

@ -0,0 +1,140 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.orm.properties;
import java.util.ArrayList;
import java.util.List;
/**
* @author Steve Ebersole
*/
public class SettingWorkingDetails {
private final String name;
private final String settingsClassName;
private final String settingFieldName;
private final String publishedJavadocLink;
private String defaultValue;
private String apiNote;
private String since;
private boolean deprecated;
private boolean incubating;
private List<String> relatedSettingNames;
public SettingWorkingDetails(
String name,
String settingsClassName,
String settingFieldName,
String publishedJavadocLink) {
this.name = name;
this.settingsClassName = settingsClassName;
this.settingFieldName = settingFieldName;
this.publishedJavadocLink = publishedJavadocLink;
}
public String getName() {
return name;
}
public String getSettingsClassName() {
return settingsClassName;
}
public String getSettingFieldName() {
return settingFieldName;
}
public String getPublishedJavadocLink() {
return publishedJavadocLink;
}
public String getDefaultValue() {
return defaultValue;
}
public void setDefaultValue(String defaultValue) {
this.defaultValue = defaultValue;
}
public String getApiNote() {
return apiNote;
}
public void setApiNote(String apiNote) {
this.apiNote = apiNote;
}
public String getSince() {
return since;
}
public void setSince(String since) {
this.since = since;
}
public boolean isDeprecated() {
return deprecated;
}
public void setDeprecated(boolean deprecated) {
this.deprecated = deprecated;
}
public boolean isIncubating() {
return incubating;
}
public void setIncubating(boolean incubating) {
this.incubating = incubating;
}
public List<String> getRelatedSettingNames() {
return relatedSettingNames;
}
public void addRelatedSettingName(String settingName) {
if ( relatedSettingNames == null ) {
relatedSettingNames = new ArrayList<>();
}
relatedSettingNames.add( settingName );
}
public SettingDescriptor buildDescriptor(String asciidoc) {
if ( name == null ) {
throw new IllegalStateException( "Setting name not specified" );
}
if ( settingsClassName == null ) {
throw new IllegalStateException( "Setting constant class-name not specified" );
}
if ( settingFieldName == null ) {
throw new IllegalStateException( "Setting constant field-name not specified" );
}
if ( publishedJavadocLink == null ) {
throw new IllegalStateException( "Setting javadoc link not specified" );
}
if ( asciidoc == null ) {
throw new IllegalStateException( "Setting comment not specified" );
}
return new SettingDescriptor(
name,
settingsClassName,
settingFieldName,
publishedJavadocLink,
asciidoc,
defaultValue,
apiNote,
since,
deprecated,
incubating
);
}
}

View File

@ -16,8 +16,6 @@ import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.provider.Property; import org.gradle.api.provider.Property;
import org.gradle.util.internal.ConfigureUtil; import org.gradle.util.internal.ConfigureUtil;
import org.hibernate.orm.env.HibernateVersion;
import groovy.lang.Closure; import groovy.lang.Closure;
/** /**
@ -30,6 +28,7 @@ public class SettingsDocExtension {
private final DirectoryProperty javadocDirectory; private final DirectoryProperty javadocDirectory;
private final Property<String> publishedDocsUrl; private final Property<String> publishedDocsUrl;
private final Property<String> anchorNameBase;
private final NamedDomainObjectContainer<SettingsDocSection> sections; private final NamedDomainObjectContainer<SettingsDocSection> sections;
private final RegularFileProperty outputFile; private final RegularFileProperty outputFile;
@ -38,6 +37,7 @@ public class SettingsDocExtension {
public SettingsDocExtension(Project project) { public SettingsDocExtension(Project project) {
javadocDirectory = project.getObjects().directoryProperty(); javadocDirectory = project.getObjects().directoryProperty();
publishedDocsUrl = project.getObjects().property( String.class ); publishedDocsUrl = project.getObjects().property( String.class );
anchorNameBase = project.getObjects().property( String.class );
sections = project.getObjects().domainObjectContainer( SettingsDocSection.class, SettingsDocSection::create ); sections = project.getObjects().domainObjectContainer( SettingsDocSection.class, SettingsDocSection::create );
outputFile = project.getObjects().fileProperty(); outputFile = project.getObjects().fileProperty();
@ -62,6 +62,14 @@ public class SettingsDocExtension {
return publishedDocsUrl; return publishedDocsUrl;
} }
public Property<String> getAnchorNameBase() {
return anchorNameBase;
}
public void setAnchorNameBase(String base) {
anchorNameBase.set( base );
}
/** /**
* Configuration of the sections within the generated document * Configuration of the sections within the generated document
*/ */

View File

@ -15,12 +15,14 @@ import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.file.RegularFileProperty; import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.provider.Property; import org.gradle.api.provider.Property;
import org.gradle.api.tasks.IgnoreEmptyDirectories; import org.gradle.api.tasks.IgnoreEmptyDirectories;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputDirectory; import org.gradle.api.tasks.InputDirectory;
import org.gradle.api.tasks.Nested; import org.gradle.api.tasks.Nested;
import org.gradle.api.tasks.OutputFile; import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.TaskAction; import org.gradle.api.tasks.TaskAction;
import org.hibernate.orm.env.HibernateVersion; import org.hibernate.orm.env.HibernateVersion;
import org.hibernate.orm.properties.jdk11.SettingsCollector;
import static org.hibernate.orm.properties.SettingsDocumentationPlugin.TASK_GROUP_NAME; import static org.hibernate.orm.properties.SettingsDocumentationPlugin.TASK_GROUP_NAME;
@ -34,7 +36,7 @@ public class SettingsDocGenerationTask extends DefaultTask {
private final DirectoryProperty javadocDirectory; private final DirectoryProperty javadocDirectory;
private final Property<String> publishedDocsUrl; private final Property<String> publishedDocsUrl;
private final Property<String> anchorNameBase;
private final NamedDomainObjectContainer<SettingsDocSection> sections; private final NamedDomainObjectContainer<SettingsDocSection> sections;
private final RegularFileProperty outputFile; private final RegularFileProperty outputFile;
@ -53,6 +55,9 @@ public class SettingsDocGenerationTask extends DefaultTask {
publishedDocsUrl = project.getObjects().property( String.class ); publishedDocsUrl = project.getObjects().property( String.class );
publishedDocsUrl.convention( dslExtension.getPublishedDocsUrl() ); publishedDocsUrl.convention( dslExtension.getPublishedDocsUrl() );
anchorNameBase = project.getObjects().property( String.class );
anchorNameBase.convention( dslExtension.getAnchorNameBase() );
sections = dslExtension.getSections(); sections = dslExtension.getSections();
outputFile = project.getObjects().fileProperty(); outputFile = project.getObjects().fileProperty();
@ -65,6 +70,16 @@ public class SettingsDocGenerationTask extends DefaultTask {
return javadocDirectory; return javadocDirectory;
} }
@Input
public Property<String> getPublishedDocsUrl() {
return publishedDocsUrl;
}
@Input
public Property<String> getAnchorNameBase() {
return anchorNameBase;
}
@Nested @Nested
public NamedDomainObjectContainer<SettingsDocSection> getSections() { public NamedDomainObjectContainer<SettingsDocSection> getSections() {
return sections; return sections;
@ -83,6 +98,7 @@ public class SettingsDocGenerationTask extends DefaultTask {
+ "/javadocs/"; + "/javadocs/";
AsciiDocWriter.writeToFile( AsciiDocWriter.writeToFile(
anchorNameBase.get(),
SettingsCollector.collectSettingDescriptors( SettingsCollector.collectSettingDescriptors(
javadocDirectory.get(), javadocDirectory.get(),
sections.getAsMap(), sections.getAsMap(),

View File

@ -6,23 +6,88 @@
*/ */
package org.hibernate.orm.properties; package org.hibernate.orm.properties;
import java.util.ArrayList;
import java.util.Comparator; import java.util.Comparator;
import java.util.List;
import org.gradle.api.tasks.Input; import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.Internal; import org.gradle.api.tasks.Internal;
import org.gradle.api.tasks.Optional;
import static java.util.Comparator.comparing;
/** /**
* DSL extension for defining a section in the settings appendix in the User Guide. * DSL extension for defining a section in the settings appendix in the User Guide.
* <p/>
* Specifies the settings class to match, and identifies which module (by name) the
* settings class from.
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class SettingsDocSection { public class SettingsDocSection {
public static final Comparator<SettingsDocSection> BY_NAME = comparing( SettingsDocSection::getName ); private final String name;
private Integer explicitPosition;
private String summary;
private String description;
private List<String> settingsClassNames = new ArrayList<>();
public SettingsDocSection(String name) {
this.name = name;
}
private SettingsDocSection(
String name,
Integer explicitPosition) {
this.name = name;
this.explicitPosition = explicitPosition;
}
@Internal
public String getName() {
return name;
}
@Optional
@Input
public Integer getExplicitPosition() {
return explicitPosition;
}
public void setExplicitPosition(Integer explicitPosition) {
this.explicitPosition = explicitPosition;
}
@Input
public List<String> getSettingsClassNames() {
return settingsClassNames;
}
public void setSettingsClassNames(List<String> settingsClassNames) {
this.settingsClassNames = settingsClassNames;
}
public void settingsClassName(String name) {
settingsClassNames.add( name );
}
@Input
public String getSummary() {
return summary;
}
public void setSummary(String summary) {
this.summary = summary;
}
@Input
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@Override
public String toString() {
return "SettingsDocSection(" + name + " [" + explicitPosition + "])";
}
/** /**
* Factory for SettingsDocSection instances * Factory for SettingsDocSection instances
@ -31,36 +96,22 @@ public class SettingsDocSection {
return new SettingsDocSection( name ); return new SettingsDocSection( name );
} }
private final String name; private static final Comparator<Integer> nullsLastInComparator = Comparator.nullsLast( Integer::compare );
private static final Comparator<SettingsDocSection> nameComparator = Comparator.comparing( SettingsDocSection::getName );
// todo : do we ever care about multiple settings-classes for a single project? public static int compare(SettingsDocSection section1, SettingsDocSection section2) {
private String projectPath; // todo (settings-doc) : add support for negative-as-last?
private String settingsClassName; // - as a means to easily sort "less used" values at the end (EnvironmentSettings, etc)
public SettingsDocSection(String name) { final Integer explicitPosition1 = section1.getExplicitPosition();
this.name = name; final Integer explicitPosition2 = section2.getExplicitPosition();
final int positionComparison = nullsLastInComparator.compare( explicitPosition1, explicitPosition2 );
if ( positionComparison != 0 ) {
return positionComparison;
} }
@Internal return nameComparator.compare( section1, section2 );
public String getName() {
return name;
}
@Input
public String getProjectPath() {
return projectPath;
}
public void setProjectPath(String projectPath) {
this.projectPath = projectPath;
}
@Input
public String getSettingsClassName() {
return settingsClassName;
}
public void setSettingsClassName(String settingsClassName) {
this.settingsClassName = settingsClassName;
} }
} }

View File

@ -10,7 +10,6 @@ import org.gradle.api.Plugin;
import org.gradle.api.Project; import org.gradle.api.Project;
import org.hibernate.orm.env.EnvironmentProjectPlugin; import org.hibernate.orm.env.EnvironmentProjectPlugin;
import org.hibernate.orm.env.HibernateVersion;
import static org.hibernate.orm.properties.SettingsDocExtension.EXTENSION_NAME; import static org.hibernate.orm.properties.SettingsDocExtension.EXTENSION_NAME;
import static org.hibernate.orm.properties.SettingsDocGenerationTask.TASK_NAME; import static org.hibernate.orm.properties.SettingsDocGenerationTask.TASK_NAME;

View File

@ -7,6 +7,12 @@
package org.hibernate.orm.properties; package org.hibernate.orm.properties;
import java.io.File; import java.io.File;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
@ -25,4 +31,12 @@ public class Utils {
public static String packagePrefix(String className) { public static String packagePrefix(String className) {
return className.substring( 0, className.lastIndexOf( '.' ) ); return className.substring( 0, className.lastIndexOf( '.' ) );
} }
public static Map<SettingsDocSection, SortedSet<SettingDescriptor>> createResultMap(Map<String, SettingsDocSection> sections) {
final TreeMap<SettingsDocSection, SortedSet<SettingDescriptor>> map = new TreeMap<>( SettingsDocSection::compare );
sections.forEach( (name, descriptor) -> {
map.put( descriptor, new TreeSet<>( SettingDescriptorComparator.INSTANCE ) );
} );
return map;
}
} }

View File

@ -0,0 +1,176 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.orm.properties.jdk11;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
import org.jsoup.nodes.Element;
import org.jsoup.nodes.Node;
import org.jsoup.nodes.TextNode;
import org.jsoup.select.Elements;
/**
* @author Steve Ebersole
*/
class DomToAsciidocConverter {
public static String convert(Elements elements) {
final DomToAsciidocConverter converter = new DomToAsciidocConverter();
return converter.convertInternal( elements );
}
public static String convert(Element element) {
final DomToAsciidocConverter converter = new DomToAsciidocConverter();
return converter.convertInternal( element );
}
private final Map<String, Consumer<Element>> elementVisitorsByTag = new HashMap<>();
private final StringBuilder converted = new StringBuilder();
public DomToAsciidocConverter() {
elementVisitorsByTag.put( "a", this::visitLink );
elementVisitorsByTag.put( "span", this::visitSpan );
elementVisitorsByTag.put( "ul", this::visitUl );
elementVisitorsByTag.put( "ol", this::visitUl );
elementVisitorsByTag.put( "li", this::visitLi );
elementVisitorsByTag.put( "b", this::visitBold );
elementVisitorsByTag.put( "strong", this::visitBold );
elementVisitorsByTag.put( "em", this::visitBold );
elementVisitorsByTag.put( "code", this::visitCode );
elementVisitorsByTag.put( "p", this::visitDiv );
elementVisitorsByTag.put( "div", this::visitDiv );
elementVisitorsByTag.put( "dl", this::visitDiv );
elementVisitorsByTag.put( "dd", this::visitDiv );
}
private String convertInternal(Elements elements) {
for ( Element element : elements ) {
visitElement( element );
}
return converted.toString();
}
private String convertInternal(Element element) {
visitElement( element );
return converted.toString();
}
private void visitNode(Node node) {
// We know about 2 types of nodes that we care about:
// 1. Element -- means that it is some tag,
// so we will defer the decision what to do about it to the visitElement.
// 2. TextNode -- simple text that we'll just add to the converted result.
//
// If we encounter something else -- let's fail,
// so we can investigate what new element type it is and decide what to do about it.
if ( node instanceof Element ) {
visitElement( ( (Element) node ) );
}
else if ( node instanceof TextNode ) {
visitTextNode( (TextNode) node );
}
else {
visitUnknownNode( node );
}
}
private void visitElement(Element element) {
String tag = element.tagName();
Consumer<Element> visitor = elementVisitorsByTag.get( tag );
if ( visitor == null ) {
// If we encounter an element that we are not handling --
// we want to fail as the result might be missing some details:
throw new IllegalStateException( "Unknown element: " + element );
}
visitor.accept( element );
}
private void visitDiv(Element div) {
if ( converted.length() != 0 ) {
converted.append( "\n+\n" );
}
for ( Node childNode : div.childNodes() ) {
visitNode( childNode );
}
converted.append( '\n' );
}
private void visitCode(Element code) {
converted.append( "`" );
for ( Node childNode : code.childNodes() ) {
visitNode( childNode );
}
converted.append( "`" );
}
private void visitBold(Element bold) {
converted.append( "**" );
for ( Node childNode : bold.childNodes() ) {
visitNode( childNode );
}
converted.append( "**" );
}
private void visitLi(Element li) {
converted.append( "\n * " );
for ( Node childNode : li.childNodes() ) {
visitNode( childNode );
}
}
private void visitUl(Element ul) {
if ( converted.lastIndexOf( "\n" ) != converted.length() - 1 ) {
converted.append( '\n' );
}
converted.append( "+\n" );
for ( Node childNode : ul.childNodes() ) {
visitNode( childNode );
}
}
private void visitSpan(Element span) {
// If it is a label for deprecation, let's make it bold to stand out:
boolean deprecatedLabel = span.hasClass( "deprecatedLabel" );
if ( deprecatedLabel ) {
converted.append( "**" );
}
for ( Node childNode : span.childNodes() ) {
visitNode( childNode );
}
if ( deprecatedLabel ) {
converted.append( "**" );
}
}
private void visitLink(Element link) {
converted.append( "link:" )
.append( link.attr( "href" ) )
.append( '[' );
for ( Node childNode : link.childNodes() ) {
visitNode( childNode );
}
converted.append( ']' );
}
private void visitTextNode(TextNode node) {
if ( converted.lastIndexOf( "+\n" ) == converted.length() - "+\n".length() ) {
// if it's a start of a paragraph - remove any leading spaces:
converted.append( ( node ).text().replaceAll( "^\\s+", "" ) );
}
else {
converted.append( ( node ).text() );
}
}
private void visitUnknownNode(Node node) {
// if we encounter a node that we are not handling - we want to fail as the result might be missing some details:
throw new IllegalStateException( "Unknown node: " + node );
}
}

View File

@ -0,0 +1,359 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.orm.properties.jdk11;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.SortedSet;
import org.gradle.api.file.Directory;
import org.hibernate.orm.properties.SettingDescriptor;
import org.hibernate.orm.properties.SettingWorkingDetails;
import org.hibernate.orm.properties.SettingsDocSection;
import org.hibernate.orm.properties.Utils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import static org.hibernate.orm.properties.Utils.packagePrefix;
import static org.hibernate.orm.properties.Utils.withoutPackagePrefix;
/**
* Processes Javadoc into SettingDescriptor based on the JDK 11 javadoc format
*
* @author Marko Bekhta
* @author Steve Ebersole
*/
public class SettingsCollector {
public static Map<SettingsDocSection, SortedSet<SettingDescriptor>> collectSettingDescriptors(
Directory javadocDirectory,
Map<String, SettingsDocSection> sections,
String publishedJavadocsUrl) {
return collectSettingDescriptors( javadocDirectory.getAsFile(), sections, publishedJavadocsUrl );
}
public static Map<SettingsDocSection, SortedSet<SettingDescriptor>> collectSettingDescriptors(
File javadocDirectory,
Map<String, SettingsDocSection> sections,
String publishedJavadocsUrl) {
final Map<SettingsDocSection, SortedSet<SettingDescriptor>> result = Utils.createResultMap( sections );
// Load the constant-values.html file with Jsoup and start processing it
final Document constantValuesDocument = loadConstants( javadocDirectory );
// For each <table class="constantsSummary"/> Element in constant-values.html...
for ( Element table : constantValuesDocument.select( "table.constantsSummary" ) ) {
// e.g. org.hibernate.cfg.JdbcSettings
final String className = table.selectFirst( "caption" ).text();
// find the doc section descriptor defined for this class, if one
final SettingsDocSection docSection = findMatchingDocSection( className, sections );
if ( docSection == null ) {
// does not match any defined sections, skip it
continue;
}
// todo (settings-doc) : consider extracting all @see tags and grabbing ones that refer to other "setting field"
// and ultimately render "cross links" - i.e. `@see JdbcSettings#JAKARTA_JDBC_URL`.
// - or even handling all "setting constant" links this way
// - these are contained as notes in the Javadoc.
// - this would require a second pass though after all "setting details" have bee processed.
// - we don't need this until ^^
//final Map<String, SettingWorkingDetails> settingWorkingDetailsMap = new HashMap<>();
// Load the Javadoc HTML for the constants class, e.g. org.hibernate.cfg.JdbcSettings
final Document constantsClassDocument = loadClassJavadoc( className, javadocDirectory );
// go through constants from constant-values.html
for ( Element row : table.select( "tr" ) ) {
if ( row.hasClass( "altColor" ) || row.hasClass( "rowColor" ) ) {
// <td class="colFirst">
// <a id="org.hibernate.cfg.JdbcSettings.DIALECT">
final String constantFieldFqn = row.selectFirst( ".colFirst a" ).id();
final String simpleFieldName = constantFieldFqn.substring( constantFieldFqn.lastIndexOf( '.' ) + 1 );
// <td class="colLast"><code>"hibernate.dialect"</code></td>
final String constantValue = row.selectFirst( ".colLast" ).text();
final String settingName = stripQuotes( constantValue );
// locate the blockList for the field from the constants class Javadoc
//
// <a id="DIALECT">
// <!-- -->
// </a>
// <ul class="blockList">
// <li class="blockList">
// <h4>DIALECT</h4>
// ..
// <div class="block">{COMMENT}</div>
// <dl>
// <!-- "notes" -->
// </dl>
// </li>
// </ul>
final Element fieldJavadocBlockList = constantsClassDocument.selectFirst( "#" + simpleFieldName + " + ul li.blockList" );
if ( fieldJavadocBlockList == null || isUselessJavadoc( fieldJavadocBlockList ) ) {
System.out.println( className + "#" + simpleFieldName + " defined no Javadoc - ignoring." );
continue;
}
final SettingWorkingDetails settingWorkingDetails = new SettingWorkingDetails(
settingName,
className,
simpleFieldName,
Utils.fieldJavadocLink(
publishedJavadocsUrl,
className,
simpleFieldName
)
);
applyMetadata( className, publishedJavadocsUrl, settingWorkingDetails, fieldJavadocBlockList );
final Elements javadocsToConvert = cleanupFieldJavadocElement( fieldJavadocBlockList, className, publishedJavadocsUrl );
final SettingDescriptor settingDescriptor = settingWorkingDetails.buildDescriptor(
DomToAsciidocConverter.convert( javadocsToConvert )
);
final SortedSet<SettingDescriptor> docSectionSettings = result.get( docSection );
docSectionSettings.add( settingDescriptor );
}
}
}
return result;
}
public static Document loadConstants(File javadocDirectory) {
try {
final File constantValuesFile = new File( javadocDirectory, "constant-values.html" );
return Jsoup.parse( constantValuesFile );
}
catch (IOException e) {
throw new IllegalStateException( "Unable to access javadocs `constant-values.html`", e );
}
}
private static Document loadClassJavadoc(String enclosingClass, File javadocDirectory) {
final String classJavadocFileName = enclosingClass.replace( ".", File.separator ) + ".html";
final File classJavadocFile = new File( javadocDirectory, classJavadocFileName );
try {
return Jsoup.parse( classJavadocFile );
}
catch (IOException e) {
throw new RuntimeException( "Unable to access javadocs for " + enclosingClass, e );
}
}
/**
* @param fieldJavadocElement The element to inspect if it has some valuable documentation.
* @return {@code true} if no Javadoc was written for this field; {@code false} otherwise.
*/
private static boolean isUselessJavadoc(Element fieldJavadocElement) {
return fieldJavadocElement.selectFirst( "div.block" ) == null;
}
private static void applyMetadata(
String className,
String publishedJavadocsUrl,
SettingWorkingDetails settingDetails,
Element fieldJavadocElement) {
processNotes(
fieldJavadocElement,
(name, content) -> {
switch ( name ) {
case "Default Value:": {
fixUrls( className, publishedJavadocsUrl, content );
final String defaultValueText = DomToAsciidocConverter.convert( content );
settingDetails.setDefaultValue( defaultValueText );
break;
}
case "API Note:": {
settingDetails.setApiNote( content.text() );
break;
}
case "Since:": {
settingDetails.setSince( content.text() );
break;
}
}
}
);
settingDetails.setIncubating( interpretIncubation( fieldJavadocElement ) );
settingDetails.setDeprecated( interpretDeprecation( fieldJavadocElement ) );
}
private static SettingsDocSection findMatchingDocSection(
String className,
Map<String, SettingsDocSection> sections) {
for ( Map.Entry<String, SettingsDocSection> entry : sections.entrySet() ) {
if ( entry.getValue().getSettingsClassNames().contains( className ) ) {
return entry.getValue();
}
}
return null;
}
private static String stripQuotes(String value) {
if ( value.startsWith( "\"" ) && value.endsWith( "\"" ) ) {
return value.substring( 1, value.length() - 1 );
}
return value;
}
@FunctionalInterface
private interface NoteConsumer {
void consumeNote(String name, Element content);
}
private static void processNotes(
Element fieldJavadocElement,
NoteConsumer noteConsumer) {
final Element notesElement = fieldJavadocElement.selectFirst( "dl" );
if ( notesElement == null ) {
return;
}
// should be a list of alternating <dt/> and <dd/> elements.
final Elements notesChildren = notesElement.children();
for ( int i = 0; i < notesChildren.size(); i+=2 ) {
final Element dtNode = notesChildren.get( i );
if ( !dtNode.tagName().equals( "dt" ) ) {
throw new RuntimeException( "Unexpected Javadoc format" );
}
final Element ddNode = notesChildren.get( i+1 );
if ( !ddNode.tagName().equals( "dd" ) ) {
throw new RuntimeException( "Unexpected Javadoc format" );
}
noteConsumer.consumeNote( dtNode.text().trim(), ddNode );
}
}
private static boolean interpretIncubation(Element fieldJavadocElement) {
final Element incubatingMarkerElement = fieldJavadocElement.selectFirst( "[href*=.Incubating.html]" );
return incubatingMarkerElement != null;
}
private static boolean interpretDeprecation(Element fieldJavadocElement) {
// A setting is considered deprecated with either `@Deprecated`
final Element deprecationDiv = fieldJavadocElement.selectFirst( ".deprecationBlock" );
// presence of this <div/> indicates the member is deprecated
if ( deprecationDiv != null ) {
return true;
}
// or `@Remove`
final Element removeMarkerElement = fieldJavadocElement.selectFirst( "[href*=.Remove.html]" );
if ( removeMarkerElement != null ) {
return true;
}
return false;
}
private static Elements cleanupFieldJavadocElement(
Element fieldJavadocElement,
String className,
String publishedJavadocsUrl) {
// Before proceeding let's make sure that the javadoc structure is the one that we expect:
if ( !isValidFieldJavadocStructure( fieldJavadocElement ) ) {
throw new IllegalStateException(
"Javadoc's DOM doesn't match the expected structure. " +
"This may lead to unexpected results in rendered configuration properties in the User Guide."
);
}
fixUrls( className, publishedJavadocsUrl, fieldJavadocElement );
final Elements usefulDocsPart = new Elements();
// We want to take the javadoc comment block...
final Element javadocComment = fieldJavadocElement.selectFirst( "div.block" );
usefulDocsPart.add( javadocComment );
return usefulDocsPart;
}
/**
* Any ORM links will be relative, and we want to prepend them with the {@code publishedJavadocsUrl}
* so that they are usable when the doc is published.
* Any external links should have a {@code externalLink} or {@code external-link} CSS class, we want to keep them unchanged.
* <p>
* NOTE: this method modifies the parsed DOM.
*/
private static void fixUrls(
String className,
String publishedJavadocsUrl,
Element fieldJavadocElement) {
for ( Element link : fieldJavadocElement.getElementsByTag( "a" ) ) {
// only update links if they are not external:
if ( !isExternalLink( link ) ) {
String href = link.attr( "href" );
if ( href.startsWith( "#" ) ) {
href = withoutPackagePrefix( className ) + ".html" + href;
}
String packagePath = packagePrefix( className ).replace( ".", File.separator );
href = publishedJavadocsUrl + packagePath + "/" + href;
link.attr( "href", href );
}
}
}
private static boolean isExternalLink(Element link) {
String href = link.attr( "href" );
return link.hasClass( "externalLink" )
|| link.hasClass( "external-link" )
|| href != null && href.startsWith( "http" );
}
private static boolean isValidFieldJavadocStructure(Element fieldJavadocElement) {
// Field's DOM sub-structure that we are expecting should be:
//
// <ul class="blockList">
// <li class="blockList">
// <h4>DIALECT</h4>
// <pre>
// <!-- might have @Incubating, @Deprecated or @Remove
// </pre>
// ...
// <div class="block">{COMMENT}</div>
// <dl>
// <!-- "notes" -->
// </dl>
// </li>
// </ul>
if ( !"li".equals( fieldJavadocElement.tagName() ) ) {
return false;
}
if ( !fieldJavadocElement.hasClass( "blockList" ) ) {
return false;
}
if ( fieldJavadocElement.selectFirst( "div.block" ) == null
&& fieldJavadocElement.selectFirst( "dl" ) == null
&& fieldJavadocElement.selectFirst( "pre" ) == null ) {
return false;
}
return true;
}
}

View File

@ -4,23 +4,15 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. * License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html. * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/ */
package org.hibernate.orm.properties; package org.hibernate.orm.properties.jdk17;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.function.Consumer; import java.util.function.Consumer;
import org.gradle.api.file.Directory; import org.hibernate.orm.properties.Utils;
import org.gradle.api.file.RegularFile;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element; import org.jsoup.nodes.Element;
import org.jsoup.nodes.Node; import org.jsoup.nodes.Node;
import org.jsoup.nodes.TextNode; import org.jsoup.nodes.TextNode;
@ -30,178 +22,9 @@ import static org.hibernate.orm.properties.Utils.packagePrefix;
import static org.hibernate.orm.properties.Utils.withoutPackagePrefix; import static org.hibernate.orm.properties.Utils.withoutPackagePrefix;
/** /**
* @author Marko Bekhta
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class SettingsCollector { public class JavadocToAsciidocConverter {
public static SortedMap<SettingsDocSection, SortedSet<SettingDescriptor>> collectSettingDescriptors(
Directory javadocDirectory,
Map<String, SettingsDocSection> sections,
String publishedJavadocsUrl) {
final SortedMap<SettingsDocSection, SortedSet<SettingDescriptor>> result = new TreeMap<>( SettingsDocSection.BY_NAME );
// Load the constant-values.html file with Jsoup and start processing it
final Document constantValuesJson = loadConstants( javadocDirectory );
final Elements blockLists = constantValuesJson.select( "ul.block-list" );
final Map<String,Map<String, Element>> fieldJavadocsByClass = new HashMap<>();
for ( int bl = 0; bl < blockLists.size(); bl++ ) {
final Element blockList = blockLists.get( bl );
final String className = blockList.selectFirst( "span" ).text();
// find the doc section descriptor defined for this class, if one
final SettingsDocSection docSection = findMatchingDocSection( className, sections );
if ( docSection == null ) {
// does not match any defined sections, skip it
continue;
}
final SortedSet<SettingDescriptor> docSectionSettings = findSettingDescriptors( docSection, result );
final Map<String, Element> classFieldJavadocs = extractClassFieldJavadocs( className, javadocDirectory, fieldJavadocsByClass );
final Element tableDiv = blockList.selectFirst( ".summary-table" );
final Elements constantFqnColumns = tableDiv.select( ".col-first" );
final Elements constantValueColumns = tableDiv.select( ".col-last" );
for ( int c = 0; c < constantFqnColumns.size(); c++ ) {
final Element constantFqnColumn = constantFqnColumns.get( c );
if ( constantFqnColumn.hasClass( "table-header" ) ) {
continue;
}
final String constantFqn = constantFqnColumn.selectFirst( "code" ).id();
final String constantValue = constantValueColumns.get( c ).selectFirst( "code" ).text();
// locate the field javadoc from `classFieldJavadocs`.
// that map is keyed by the simple name of the field, so strip the
// package and class name from `constantFqn` to do the look-up
//
// NOTE : there may be no Javadoc, in which case the Element will be null;
// there is literally no such div in these cases
final String simpleFieldName = constantFqn.substring( constantFqn.lastIndexOf( '.' ) + 1 );
final Element fieldJavadocElement = classFieldJavadocs.get( simpleFieldName );
if ( fieldJavadocElement == null || isUselessJavadoc( fieldJavadocElement ) ) {
System.out.println( "There was no javadoc found for " + className + "#" + simpleFieldName
+ ". Ignoring this setting." );
continue;
}
final SettingDescriptor settingDescriptor = new SettingDescriptor(
stripQuotes( constantValue ),
className,
simpleFieldName,
convertFieldJavadocHtmlToAsciidoc(
fieldJavadocElement,
className,
simpleFieldName,
publishedJavadocsUrl
),
interpretDeprecation( fieldJavadocElement ),
interpretIncubation( fieldJavadocElement )
);
docSectionSettings.add( settingDescriptor );
}
}
return result;
}
public static Document loadConstants(Directory javadocDirectory) {
try {
final File constantValuesFile = javadocDirectory.file( "constant-values.html" ).getAsFile();
return Jsoup.parse( constantValuesFile );
}
catch (IOException e) {
throw new IllegalStateException( "Unable to access javadocs `constant-values.html`", e );
}
}
private static SettingsDocSection findMatchingDocSection(
String className,
Map<String, SettingsDocSection> sections) {
for ( Map.Entry<String, SettingsDocSection> entry : sections.entrySet() ) {
if ( entry.getValue().getSettingsClassName().equals( className ) ) {
return entry.getValue();
}
}
return null;
}
private static SortedSet<SettingDescriptor> findSettingDescriptors(
SettingsDocSection docSection,
SortedMap<SettingsDocSection, SortedSet<SettingDescriptor>> map) {
final SortedSet<SettingDescriptor> existing = map.get( docSection );
if ( existing != null ) {
return existing;
}
final SortedSet<SettingDescriptor> created = new TreeSet<>( SettingDescriptor.BY_NAME );
map.put( docSection, created );
return created;
}
private static Map<String, Element> extractClassFieldJavadocs(
String className,
Directory javadocDirectory,
Map<String, Map<String, Element>> fieldJavadocsByClass) {
final Map<String, Element> existing = fieldJavadocsByClass.get( className );
if ( existing != null ) {
return existing;
}
final Map<String, Element> result = new HashMap<>();
final Document document = loadClassJavadoc( className, javadocDirectory );
final Elements fieldDetailSections = document.select( "section.detail" );
for ( Element fieldDetailSection : fieldDetailSections ) {
final String fieldName = fieldDetailSection.id();
result.put( fieldName, fieldDetailSection );
}
return result;
}
private static Document loadClassJavadoc(String enclosingClass, Directory javadocDirectory) {
final String classJavadocFileName = enclosingClass.replace( ".", File.separator ) + ".html";
final RegularFile classJavadocFile = javadocDirectory.file( classJavadocFileName );
try {
return Jsoup.parse( classJavadocFile.getAsFile() );
}
catch (IOException e) {
throw new RuntimeException( "Unable to access javadocs for " + enclosingClass, e );
}
}
private static String stripQuotes(String value) {
if ( value.startsWith( "\"" ) && value.endsWith( "\"" ) ) {
return value.substring( 1, value.length() - 1 );
}
return value;
}
private static boolean interpretDeprecation(Element fieldJavadocElement) {
// A setting is considered deprecated with either `@Deprecated`
final Element deprecationDiv = fieldJavadocElement.selectFirst( ".deprecation-block" );
// presence of this <div/> indicates the member is deprecated
if ( deprecationDiv != null ) {
return true;
}
// or `@Remove`
final Element removeMarkerElement = fieldJavadocElement.selectFirst( "[href*=Remove.html]" );
if ( removeMarkerElement != null ) {
return true;
}
return false;
}
private static boolean interpretIncubation(Element fieldJavadocElement) {
final Element incubatingMarkerElement = fieldJavadocElement.selectFirst( "[href*=Incubating.html]" );
return incubatingMarkerElement != null;
}
/** /**
* Convert the DOM representation of the field Javadoc to Asciidoc format * Convert the DOM representation of the field Javadoc to Asciidoc format
@ -211,7 +34,7 @@ public class SettingsCollector {
* @param simpleFieldName The name of the field defining the setting (relative to {@code className}) * @param simpleFieldName The name of the field defining the setting (relative to {@code className})
* @param publishedJavadocsUrl The (versioned) URL to Javadocs on the doc server * @param publishedJavadocsUrl The (versioned) URL to Javadocs on the doc server
*/ */
private static String convertFieldJavadocHtmlToAsciidoc( public static String convertFieldJavadocHtmlToAsciidoc(
Element fieldJavadocElement, Element fieldJavadocElement,
String className, String className,
String simpleFieldName, String simpleFieldName,
@ -307,14 +130,6 @@ public class SettingsCollector {
return true; return true;
} }
/**
* @param fieldJavadocElement The element to inspect if it has some valuable documentation.
* @return {@code true} if no Javadoc was written for this field; {@false otherwise}.
*/
private static boolean isUselessJavadoc(Element fieldJavadocElement) {
return fieldJavadocElement.selectFirst( "div.block" ) == null;
}
private static class DomToAsciidocConverter { private static class DomToAsciidocConverter {
private final Map<String, Consumer<Element>> elementVisitorsByTag = new HashMap<>(); private final Map<String, Consumer<Element>> elementVisitorsByTag = new HashMap<>();
private final StringBuilder converted = new StringBuilder(); private final StringBuilder converted = new StringBuilder();

View File

@ -0,0 +1,270 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.orm.properties.jdk17;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedSet;
import org.gradle.api.file.Directory;
import org.hibernate.orm.properties.SettingDescriptor;
import org.hibernate.orm.properties.SettingWorkingDetails;
import org.hibernate.orm.properties.SettingsDocSection;
import org.hibernate.orm.properties.Utils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import static org.hibernate.orm.properties.jdk17.JavadocToAsciidocConverter.convertFieldJavadocHtmlToAsciidoc;
/**
* @author Marko Bekhta
* @author Steve Ebersole
*/
public class SettingsCollector {
public static Map<SettingsDocSection, SortedSet<SettingDescriptor>> collectSettingDescriptors(
Directory javadocDirectory,
Map<String, SettingsDocSection> sections,
String publishedJavadocsUrl) {
return collectSettingDescriptors( javadocDirectory.getAsFile(), sections, publishedJavadocsUrl );
}
public static Map<SettingsDocSection, SortedSet<SettingDescriptor>> collectSettingDescriptors(
File javadocDirectory,
Map<String, SettingsDocSection> sections,
String publishedJavadocsUrl) {
final Map<SettingsDocSection, SortedSet<SettingDescriptor>> result = Utils.createResultMap( sections );
// Load the constant-values.html file with Jsoup and start processing it
final Document constantValuesJson = loadConstants( javadocDirectory );
final Elements captionClassDivs = constantValuesJson.select( "div.caption" );
for ( Element captionClassDiv : captionClassDivs ) {
final String className = captionClassDiv.selectFirst( "span" ).text();
// find the doc section descriptor defined for this class, if one
final SettingsDocSection docSection = findMatchingDocSection( className, sections );
if ( docSection == null ) {
// does not match any defined sections, skip it
continue;
}
// find the summary-table div that contains the constant->value mappings for class-name
final Element captionClassDivParent = captionClassDiv.parent();
final Element tableDiv = captionClassDivParent.selectFirst( ".summary-table" );
final Elements constantFqnColumns = tableDiv.select( ".col-first" );
final Elements constantValueColumns = tableDiv.select( ".col-last" );
// extract the Javadoc elements for each field on class-name
final Map<String, Element> classFieldJavadocs = extractClassFieldJavadocs( className, javadocDirectory );
// todo (settings-doc) : consider extracting all @see tags and grabbing ones that refer to other "setting field"
// and ultimately render "cross links" - i.e. `@see JdbcSettings#JAKARTA_JDBC_URL`.
// these are contained as notes in the Javadoc.
// this would require a second pass though after all "setting details" have bee processed.
// for now, we don't need this
//final Map<String, SettingWorkingDetails> settingWorkingDetailsMap = new HashMap<>();
for ( int c = 0; c < constantFqnColumns.size(); c++ ) {
final Element constantFqnColumn = constantFqnColumns.get( c );
if ( constantFqnColumn.hasClass( "table-header" ) ) {
continue;
}
final String constantFqn = constantFqnColumn.selectFirst( "code" ).id();
final String constantValue = constantValueColumns.get( c ).selectFirst( "code" ).text();
// locate the field javadoc from `classFieldJavadocs`.
// that map is keyed by the simple name of the field, so strip the
// package and class name from `constantFqn` to do the look-up
//
// NOTE : there may be no Javadoc, in which case the Element will be null;
// there is literally no such div in these cases
final String simpleFieldName = constantFqn.substring( constantFqn.lastIndexOf( '.' ) + 1 );
final Element fieldJavadocElement = classFieldJavadocs.get( simpleFieldName );
if ( fieldJavadocElement == null || isUselessJavadoc( fieldJavadocElement ) ) {
System.out.println( className + "#" + simpleFieldName + " defined no Javadoc - ignoring." );
continue;
}
final String settingName = stripQuotes( constantValue );
final SettingWorkingDetails settingWorkingDetails = new SettingWorkingDetails(
settingName,
className,
simpleFieldName,
Utils.fieldJavadocLink(
publishedJavadocsUrl,
className,
simpleFieldName
)
);
applyMetadata( settingWorkingDetails, fieldJavadocElement );
// todo (settings-doc) : here is where we'd add to the `settingWorkingDetailsMap`
//settingWorkingDetailsMap.put( .., settingWorkingDetails );
// for now though, just generate the SettingDescriptor
final SettingDescriptor settingDescriptor = settingWorkingDetails.buildDescriptor(
convertFieldJavadocHtmlToAsciidoc(
fieldJavadocElement,
className,
simpleFieldName,
publishedJavadocsUrl
)
);
final SortedSet<SettingDescriptor> docSectionSettings = result.get( docSection );
docSectionSettings.add( settingDescriptor );
}
}
return result;
}
/**
* @param fieldJavadocElement The element to inspect if it has some valuable documentation.
* @return {@code true} if no Javadoc was written for this field; {@code false} otherwise.
*/
private static boolean isUselessJavadoc(Element fieldJavadocElement) {
return fieldJavadocElement.selectFirst( "div.block" ) == null;
}
private static void applyMetadata(SettingWorkingDetails settingDetails, Element fieldJavadocElement) {
processNotes(
fieldJavadocElement,
(name, content) -> {
switch ( name ) {
case "Default Value:": {
settingDetails.setDefaultValue( content );
break;
}
case "API Note:": {
settingDetails.setApiNote( content );
break;
}
case "Since:": {
settingDetails.setSince( content );
break;
}
}
}
);
settingDetails.setIncubating( interpretIncubation( fieldJavadocElement ) );
settingDetails.setDeprecated( interpretDeprecation( fieldJavadocElement ) );
}
public static Document loadConstants(File javadocDirectory) {
try {
final File constantValuesFile = new File( javadocDirectory, "constant-values.html" );
return Jsoup.parse( constantValuesFile );
}
catch (IOException e) {
throw new IllegalStateException( "Unable to access javadocs `constant-values.html`", e );
}
}
private static SettingsDocSection findMatchingDocSection(
String className,
Map<String, SettingsDocSection> sections) {
for ( Map.Entry<String, SettingsDocSection> entry : sections.entrySet() ) {
if ( entry.getValue().getSettingsClassNames().contains( className ) ) {
return entry.getValue();
}
}
return null;
}
private static Map<String, Element> extractClassFieldJavadocs(String className, File javadocDirectory) {
final Map<String, Element> result = new HashMap<>();
final Document document = loadClassJavadoc( className, javadocDirectory );
final Elements fieldDetailSections = document.select( "section.detail" );
for ( Element fieldDetailSection : fieldDetailSections ) {
final String fieldName = fieldDetailSection.id();
result.put( fieldName, fieldDetailSection );
}
return result;
}
private static Document loadClassJavadoc(String enclosingClass, File javadocDirectory) {
final String classJavadocFileName = enclosingClass.replace( ".", File.separator ) + ".html";
final File classJavadocFile = new File( javadocDirectory, classJavadocFileName );
try {
return Jsoup.parse( classJavadocFile );
}
catch (IOException e) {
throw new RuntimeException( "Unable to access javadocs for " + enclosingClass, e );
}
}
private static String stripQuotes(String value) {
if ( value.startsWith( "\"" ) && value.endsWith( "\"" ) ) {
return value.substring( 1, value.length() - 1 );
}
return value;
}
@FunctionalInterface
private interface NoteConsumer {
void consumeNote(String name, String content);
}
private static void processNotes(
Element fieldJavadocElement,
NoteConsumer noteConsumer) {
final Element notesElement = fieldJavadocElement.selectFirst( "dl.notes" );
if ( notesElement == null ) {
return;
}
// should be a list of alternating <dt/> and <dd/> elements.
final Elements notesChildren = notesElement.children();
for ( int i = 0; i < notesChildren.size(); i+=2 ) {
final Element dtNode = notesChildren.get( i );
if ( !dtNode.tagName().equals( "dt" ) ) {
throw new RuntimeException( "Unexpected Javadoc format" );
}
final Element ddNode = notesChildren.get( i+1 );
if ( !ddNode.tagName().equals( "dd" ) ) {
throw new RuntimeException( "Unexpected Javadoc format" );
}
noteConsumer.consumeNote( dtNode.text().trim(), ddNode.text().trim() );
}
}
private static boolean interpretIncubation(Element fieldJavadocElement) {
final Element incubatingMarkerElement = fieldJavadocElement.selectFirst( "[href*=.Incubating.html]" );
return incubatingMarkerElement != null;
}
private static boolean interpretDeprecation(Element fieldJavadocElement) {
// A setting is considered deprecated with either `@Deprecated`
final Element deprecationDiv = fieldJavadocElement.selectFirst( ".deprecation-block" );
// presence of this <div/> indicates the member is deprecated
if ( deprecationDiv != null ) {
return true;
}
// or `@Remove`
final Element removeMarkerElement = fieldJavadocElement.selectFirst( "[href*=.Remove.html]" );
if ( removeMarkerElement != null ) {
return true;
}
return false;
}
}

View File

@ -64,8 +64,8 @@ public class JavaModulePlugin implements Plugin<Project> {
javaPluginExtension.getToolchain().getLanguageVersion().set( jdkVersionsConfig.getMainCompileVersion() ); javaPluginExtension.getToolchain().getLanguageVersion().set( jdkVersionsConfig.getMainCompileVersion() );
configureCompileTasks( project ); configureCompileTasks( project );
configureJavadocTasks( project );
configureTestTasks( project ); configureTestTasks( project );
configureJavadocTasks( project, mainSourceSet );
configureCompileTask( mainCompileTask, jdkVersionsConfig.getMainReleaseVersion() ); configureCompileTask( mainCompileTask, jdkVersionsConfig.getMainReleaseVersion() );
configureCompileTask( testCompileTask, jdkVersionsConfig.getTestReleaseVersion() ); configureCompileTask( testCompileTask, jdkVersionsConfig.getTestReleaseVersion() );
@ -117,24 +117,6 @@ public class JavaModulePlugin implements Plugin<Project> {
} ); } );
} }
private void configureJavadocTasks(Project project) {
project.getTasks().withType( Javadoc.class ).configureEach( new Action<Javadoc>() {
@Override
public void execute(Javadoc javadocTask) {
javadocTask.getOptions().setJFlags( javadocFlags( project ) );
javadocTask.doFirst( new Action<Task>() {
@Override
public void execute(Task task) {
project.getLogger().lifecycle(
"Generating javadoc with '{}}'",
javadocTask.getJavadocTool().get().getMetadata().getInstallationPath()
);
}
} );
}
} );
}
private void configureTestTasks(Project project) { private void configureTestTasks(Project project) {
project.getTasks().withType( Test.class ).configureEach( new Action<Test>() { project.getTasks().withType( Test.class ).configureEach( new Action<Test>() {
@Override @Override
@ -166,6 +148,21 @@ public class JavaModulePlugin implements Plugin<Project> {
} ); } );
} }
private void configureJavadocTasks(Project project, SourceSet mainSourceSet) {
project.getTasks().named( mainSourceSet.getJavadocTaskName(), Javadoc.class, (task) -> {
task.getOptions().setJFlags( javadocFlags( project ) );
task.doFirst( new Action<Task>() {
@Override
public void execute(Task t) {
project.getLogger().lifecycle(
"Generating javadoc with '{}'",
task.getJavadocTool().get().getMetadata().getInstallationPath()
);
}
} );
} );
}
private static List<String> javadocFlags(Project project) { private static List<String> javadocFlags(Project project) {
final String jvmArgs = project.property( "toolchain.javadoc.jvmargs" ).toString(); final String jvmArgs = project.property( "toolchain.javadoc.jvmargs" ).toString();
final String[] splits = jvmArgs.split( " " ); final String[] splits = jvmArgs.split( " " );