HHH-18545 - Document "characteristics" of settings

This commit is contained in:
Steve Ebersole 2024-09-26 11:47:37 -05:00
parent d4ef44db00
commit 4f9035e9f8
11 changed files with 205 additions and 96 deletions

View File

@ -573,7 +573,7 @@ settingsDocumentation {
}
transaction {
explicitPosition = 6
summary = "Proxool Connection Pool Settings"
summary = "Transaction Environment Settings"
description = "Settings which control how Hibernate interacts with and manages transactions"
settingsClassName "org.hibernate.cfg.TransactionSettings"
}

View File

@ -0,0 +1,23 @@
/*
* SPDX-License-Identifier: LGPL-2.1-or-later
* Copyright Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.cfg;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.Retention;
/**
* Denotes that a setting is intended to allow applications to upgrade
* versions of Hibernate and maintain backwards compatibility with the
* older version in some specific behavior. Such settings are almost always
* considered temporary and are usually also {@linkplain Deprecated deprecated}.
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Compatibility {
}

View File

@ -18,7 +18,8 @@ import jakarta.persistence.criteria.CriteriaUpdate;
public interface QuerySettings {
/**
* Boolean setting to control if the use of tech preview JSON functions in HQL is enabled.
* By default, this is {@code false} i.e. disabled since the functions are still incubating.
*
* @settingDefault {@code false} (disabled) since the functions are still incubating.
*
* @since 7.0
*/
@ -27,7 +28,8 @@ public interface QuerySettings {
/**
* Boolean setting to control if the use of tech preview XML functions in HQL is enabled.
* By default, this is {@code false} i.e. disabled since the functions are still incubating.
*
* @settingDefault {@code false} (disabled) since the functions are still incubating.
*
* @since 7.0
*/
@ -39,6 +41,8 @@ public interface QuerySettings {
* databases. By default, integer division in HQL can produce a non-integer
* on Oracle, MySQL, or MariaDB.
*
* @settingDefault {@code false}
*
* @since 6.5
*/
String PORTABLE_INTEGER_DIVISION = "hibernate.query.hql.portable_integer_division";
@ -70,10 +74,10 @@ public interface QuerySettings {
/**
* 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.
*
* @settingDefault {@code true} (enabled) - named queries are checked at startup.
*
* @see org.hibernate.boot.SessionFactoryBuilder#applyNamedQueryCheckingOnStartup(boolean)
*/
String QUERY_STARTUP_CHECKING = "hibernate.query.startup_check";
@ -102,8 +106,8 @@ public interface QuerySettings {
* {@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}.
*
* @settingDefault {@link org.hibernate.query.criteria.ValueHandlingMode#BIND}.
*
* @since 6.0.0
*
@ -119,8 +123,8 @@ public interface QuerySettings {
* of null values} sorted via the HQL {@code ORDER BY} clause, either {@code none},
* {@code first}, or {@code last}, or an instance of the enumeration
* {@link jakarta.persistence.criteria.Nulls}.
* <p>
* The default is {@code none}.
*
* @settingDefault {@code none}.
*
* @see jakarta.persistence.criteria.Nulls
* @see org.hibernate.boot.SessionFactoryBuilder#applyDefaultNullPrecedence(jakarta.persistence.criteria.Nulls)
@ -155,8 +159,8 @@ public interface QuerySettings {
/**
* When enabled, ordinal parameters (represented by the {@code ?} placeholder) in
* native queries will be ignored.
* <p>
* By default, native queries are checked for ordinal placeholders.
*
* @settingDefault {@code false} (disabled) - native queries are checked for ordinal placeholders.
*
* @see SessionFactoryOptions#getNativeJdbcParametersIgnored()
*/
@ -167,12 +171,14 @@ public interface QuerySettings {
* {@link java.sql.Time}, and {@link java.sql.Timestamp} instead of the
* datetime types from {@link java.time}, recovering the behavior of
* native queries in Hibernate 6 and earlier.
* <p>
* By default, native queries return {@link java.time.LocalDate},
* {@link java.time.LocalTime}, and {@link java.time.LocalDateTime}.
*
* @settingDefault {@code false} (disabled) - native queries return
* {@link java.time.LocalDate}, {@link java.time.LocalTime}, and
* {@link java.time.LocalDateTime}.
*
* @since 7.0
*/
@Compatibility
String NATIVE_PREFER_JDBC_DATETIME_TYPES = "hibernate.query.native.prefer_jdbc_datetime_types";
/**
@ -183,9 +189,9 @@ public interface QuerySettings {
* <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.
*
* @settingDefault {@code false} (disabled) - no exception is thrown and the
* possibility of terrible performance is left as a problem for the client to avoid.
*
* @since 5.2.13
*/
@ -203,8 +209,8 @@ public interface QuerySettings {
* <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.
*
* @settingDefault {@link org.hibernate.query.ImmutableEntityUpdateQueryHandlingMode#WARNING "warning"}
*
* @since 5.2.17
*

View File

@ -4,6 +4,7 @@
*/
package org.hibernate.cfg;
import jakarta.persistence.spi.PersistenceUnitInfo;
/**
@ -127,36 +128,6 @@ public interface TransactionSettings {
*/
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.
@ -176,4 +147,43 @@ public interface TransactionSettings {
* @see org.hibernate.boot.SessionFactoryBuilder#applyAutoFlushing(boolean)
*/
String FLUSH_BEFORE_COMPLETION = "hibernate.transaction.flush_before_completion";
/**
* 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)
*
* @apiNote Generally speaking, all access to transactional data should be done in a transaction.
*
* @see org.hibernate.boot.SessionFactoryBuilder#applyLazyInitializationOutsideTransaction(boolean)
*/
@Unsafe
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.
*
* @settingDefault {@code false} (disabled)
*
* @apiNote Generally speaking, all access to transactional data should be done in a transaction.
* Combining this with second-level caching, e.g., will cause problems.
*
* @see org.hibernate.boot.SessionFactoryBuilder#allowOutOfTransactionUpdateOperations(boolean)
*
* @since 5.2
*/
@Unsafe
String ALLOW_UPDATE_OUTSIDE_TRANSACTION = "hibernate.allow_update_outside_transaction";
}

View File

@ -0,0 +1,22 @@
/*
* SPDX-License-Identifier: LGPL-2.1-or-later
* Copyright Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.cfg;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.Retention;
/**
* Denotes that a setting is considered unsafe. Generally these are settings
* added for temporary use during porting of applications. Unsafe settings
* are largely considered unsupported.
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Unsafe {
}

View File

@ -109,6 +109,12 @@ public class AsciiDocWriter {
if ( lifecycleDetails.isDeprecated() ) {
writer.write( "WARNING: *_This setting is considered deprecated_*\n\n" );
}
if ( settingDescriptor.isUnsafe() ) {
writer.write( "WARNING: *_This setting is considered unsafe_*\n\n" );
}
if ( settingDescriptor.isCompatibility() ) {
writer.write( "INFO: *_This setting manages a certain backwards compatibility_*\n\n" );
}
if ( lifecycleDetails.getSince() != null ) {
writer.write( "*_Since:_* _" + lifecycleDetails.getSince() + "_\n\n" );

View File

@ -18,6 +18,8 @@ public class SettingDescriptor {
private final String defaultValue;
private final String apiNote;
private final LifecycleDetails lifecycleDetails;
private final boolean unsafe;
private final boolean compatibility;
public SettingDescriptor(
String name,
@ -27,6 +29,8 @@ public class SettingDescriptor {
String comment,
String defaultValue,
String apiNote,
boolean unsafe,
boolean compatibility,
LifecycleDetails lifecycleDetails) {
this.name = name;
this.settingsClassName = settingsClassName;
@ -35,6 +39,8 @@ public class SettingDescriptor {
this.publishedJavadocLink = publishedJavadocLink;
this.defaultValue = defaultValue;
this.apiNote = apiNote;
this.unsafe = unsafe;
this.compatibility = compatibility;
this.lifecycleDetails = lifecycleDetails;
}
@ -48,7 +54,9 @@ public class SettingDescriptor {
String apiNote,
String since,
boolean deprecated,
boolean incubating) {
boolean incubating,
boolean unsafe,
boolean compatibility) {
this(
name,
settingsClassName,
@ -56,6 +64,8 @@ public class SettingDescriptor {
publishedJavadocLink, comment,
defaultValue,
apiNote,
unsafe,
compatibility,
new LifecycleDetails( since, deprecated, incubating )
);
}
@ -100,6 +110,14 @@ public class SettingDescriptor {
return settingFieldName;
}
public boolean isUnsafe() {
return unsafe;
}
public boolean isCompatibility() {
return compatibility;
}
public LifecycleDetails getLifecycleDetails() {
return lifecycleDetails;
}

View File

@ -23,6 +23,8 @@ public class SettingWorkingDetails {
private String since;
private boolean deprecated;
private boolean incubating;
private boolean unsafe;
private boolean compatibility;
private List<String> relatedSettingNames;
public SettingWorkingDetails(
@ -92,6 +94,22 @@ public class SettingWorkingDetails {
this.incubating = incubating;
}
public boolean isUnsafe() {
return unsafe;
}
public void setUnsafe(boolean unsafe) {
this.unsafe = unsafe;
}
public boolean isCompatibility() {
return compatibility;
}
public void setCompatibility(boolean compatibility) {
this.compatibility = compatibility;
}
public List<String> getRelatedSettingNames() {
return relatedSettingNames;
}
@ -134,7 +152,9 @@ public class SettingWorkingDetails {
apiNote,
since,
deprecated,
incubating
incubating,
unsafe,
compatibility
);
}
}

View File

@ -14,6 +14,8 @@ import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
import org.jsoup.nodes.Element;
/**
* @author Steve Ebersole
*/
@ -39,4 +41,39 @@ public class Utils {
} );
return map;
}
public static boolean containsHref(Element fieldJavadocElement, String target) {
final String cssQuery = "a[href$=" + target + "]";
final Element incubatingMarkerElement = fieldJavadocElement.selectFirst( cssQuery );
return incubatingMarkerElement != null;
}
public static boolean interpretIncubation(Element fieldJavadocElement) {
return containsHref( fieldJavadocElement, "Incubating.html" );
}
public static boolean interpretUnsafe(Element fieldJavadocElement) {
return containsHref( fieldJavadocElement, "Unsafe.html" );
}
public static boolean interpretCompatibility(Element fieldJavadocElement) {
return containsHref( fieldJavadocElement, "Compatibility.html" );
}
public 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`
if ( containsHref( fieldJavadocElement, "Remove.html" ) ) {
return true;
}
return false;
}
}

View File

@ -23,6 +23,10 @@ import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import static org.hibernate.orm.properties.Utils.interpretCompatibility;
import static org.hibernate.orm.properties.Utils.interpretDeprecation;
import static org.hibernate.orm.properties.Utils.interpretIncubation;
import static org.hibernate.orm.properties.Utils.interpretUnsafe;
import static org.hibernate.orm.properties.Utils.packagePrefix;
import static org.hibernate.orm.properties.Utils.withoutPackagePrefix;
@ -195,6 +199,8 @@ public class SettingsCollector {
settingDetails.setIncubating( interpretIncubation( fieldJavadocElement ) );
settingDetails.setDeprecated( interpretDeprecation( fieldJavadocElement ) );
settingDetails.setUnsafe( interpretUnsafe( fieldJavadocElement ) );
settingDetails.setCompatibility( interpretCompatibility( fieldJavadocElement ) );
}
private static SettingsDocSection findMatchingDocSection(
@ -245,28 +251,6 @@ public class SettingsCollector {
}
}
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,

View File

@ -24,6 +24,10 @@ import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import static org.hibernate.orm.properties.Utils.interpretCompatibility;
import static org.hibernate.orm.properties.Utils.interpretDeprecation;
import static org.hibernate.orm.properties.Utils.interpretIncubation;
import static org.hibernate.orm.properties.Utils.interpretUnsafe;
import static org.hibernate.orm.properties.jdk17.JavadocToAsciidocConverter.convertFieldJavadocHtmlToAsciidoc;
/**
@ -160,6 +164,8 @@ public class SettingsCollector {
);
settingDetails.setIncubating( interpretIncubation( fieldJavadocElement ) );
settingDetails.setDeprecated( interpretDeprecation( fieldJavadocElement ) );
settingDetails.setUnsafe( interpretUnsafe( fieldJavadocElement ) );
settingDetails.setCompatibility( interpretCompatibility( fieldJavadocElement ) );
}
public static Document loadConstants(File javadocDirectory) {
@ -244,27 +250,4 @@ public class SettingsCollector {
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;
}
}