From 5b49d5efbaaef2eae3034d2057d8a4ae63f29774 Mon Sep 17 00:00:00 2001 From: Steve Ebersole Date: Wed, 25 Oct 2023 15:29:13 -0500 Subject: [PATCH] HHH-17164 - Proper, first-class soft-delete support HHH-17311 - Reversed soft delete support https://hibernate.atlassian.net/browse/HHH-17164 https://hibernate.atlassian.net/browse/HHH-17311 --- .../chapters/domain/soft_delete.adoc | 58 ++++++++----------- .../org/hibernate/annotations/SoftDelete.java | 3 +- migration-guide.adoc | 18 ++---- .../src/release/announcement-template.adoc | 46 +++++++++++++-- 4 files changed, 71 insertions(+), 54 deletions(-) diff --git a/documentation/src/main/asciidoc/userguide/chapters/domain/soft_delete.adoc b/documentation/src/main/asciidoc/userguide/chapters/domain/soft_delete.adoc index 714d461e18..fb028f72de 100644 --- a/documentation/src/main/asciidoc/userguide/chapters/domain/soft_delete.adoc +++ b/documentation/src/main/asciidoc/userguide/chapters/domain/soft_delete.adoc @@ -23,7 +23,7 @@ Soft delete support is defined by 3 main parts - 1. The <> which contains the indicator. 2. A <> from `Boolean` indicator value to the proper database type -3. Whether to <> the indicator values, tracking active/inactive instead +3. A <> for interpreting the stored indicator values. [[soft-delete-column]] @@ -31,8 +31,12 @@ Soft delete support is defined by 3 main parts - The column where the indicator value is stored is defined using `@SoftDelete#columnName` attribute. -When using <> mappings, the column name defaults to `active`; otherwise, it -defaults to the name `deleted`. +The default column name depends on the <> being used - + +ACTIVE:: + The default column name is `active`. +DELETED:: + The default column name is `deleted`. See <> for an example of customizing the column name. @@ -42,11 +46,11 @@ Depending on the conversion type, an appropriate check constraint may be applied [[soft-delete-conversion]] ==== Indicator conversion -The conversion is defined using a JPA <>. The "domain type" is always -`boolean`. The "relational type" can be any type, as defined by the converter; generally `BOOLEAN`, `BIT`, `INTEGER` or `CHAR`. +The conversion is defined using a Jakarta Persistence <>. The domain-type is always +`boolean`. The relational-type can be any type, as defined by the converter; generally `BOOLEAN`, `BIT`, `INTEGER` or `CHAR`. An explicit conversion can be specified using `@SoftDelete#converter`. See <> -for an example of specifying an explicit conversion. Explicit conversions can specify a custom converter or leverage the 3 +for an example of specifying an explicit conversion. Explicit conversions can specify a custom converter or leverage Hibernate-provided converters for the 3 most common cases - `NumericBooleanConverter`:: Defines conversion using `0` for `false` and `1` for `true` @@ -60,6 +64,8 @@ boolean (and bit):: the underlying type is boolean / bit and no conversion is ap numeric:: the underlying type is integer and values are converted according to `NumericBooleanConverter` character:: the underlying type is char and values are converted according to `TrueFalseConverter` +IMPORTANT: The converter should simply convert the `true` and `false`, irrespective of the <> used. Hibernate will handle applying the strategy. + [[soft-delete-entity]] ==== Entity soft delete @@ -133,35 +139,17 @@ The `@SoftDelete` annotation may also be placed at the package level, in which c entities and collections defined within the package. -[[soft-delete-reverse]] -==== Reversed soft delete +[[soft-delete-type]] +==== Strategy - SoftDeleteType -A common requirement in applications using soft delete is to track rows which are active as opposed to removed, -reversing the boolean value. For example: +Given truth values, there are 2 valid ways to interpret the values stored in the database. This +interpretation is defined by the SoftDeleteType enumeration and can be configured per-usage using +`@SoftDelete(..., strategy=ACTIVE)` or `@SoftDelete(..., strategy=DELETED)` - -[[soft-delete-reverse-example]] -.Reversed soft-delete -==== -[source,java] ----- -include::{testing-dir}/converter/reversed/TheEntity.java[tag=example-soft-delete-reverse, indent=0] ----- -==== +ACTIVE:: + Tracks rows which are active. A `true` value in the database indicates that the row is active + (non-deleted); a `false` value indicates inactive (deleted). +DELETED:: + Tracks rows which are deleted. A `true` value in the database indicates that the row is deleted; + a `false` value indicates that the row is non-deleted. -When an instance of `TheEntity` is persisted, the value `'Y'` will be inserted into the -`active` column. When an instance of `TheEntity` is removed, the column's value is updated to `'N'`. - -This example explicitly specifies the built-in `YesNoConverter`, but reversal works with any conversion -even implicit conversions - - -[[soft-delete-reverse-example-2]] -.Reversed soft-delete with implicit conversion -==== -[source,java] ----- -include::{testing-dir}/converter/reversed/TheEntity2.java[tag=example-soft-delete-reverse, indent=0] ----- -==== - -The important thing to remember is that the stored values are reversed from the "normal" soft delete state. -`active == true` is the same as `deleted == false` - both describe the same state. \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/SoftDelete.java b/hibernate-core/src/main/java/org/hibernate/annotations/SoftDelete.java index 244a1bfe1e..05f49092f4 100644 --- a/hibernate-core/src/main/java/org/hibernate/annotations/SoftDelete.java +++ b/hibernate-core/src/main/java/org/hibernate/annotations/SoftDelete.java @@ -62,8 +62,7 @@ public @interface SoftDelete { /** * (Optional) The name of the column. *

- * Default depends on {@linkplain #trackActive()} - {@code deleted} if {@code false} and - * {@code active} if {@code true}. + * Default depends on the {@linkplain #strategy() strategy} being used. * * @see SoftDeleteType#getDefaultColumnName() */ diff --git a/migration-guide.adoc b/migration-guide.adoc index 56be44f5a4..3486906267 100644 --- a/migration-guide.adoc +++ b/migration-guide.adoc @@ -19,20 +19,14 @@ earlier versions, see any other pertinent migration guides as well. [[soft-delete]] == Soft Delete -6.4 adds support for soft deletes against an entity's primary table and collection tables, using the -new `@SoftDelete` annotation. - -[source,java] ----- -@Entity -@SoftDelete -class Account { - ... -} ----- - +6.4 adds support for soft deletes, using the new `@SoftDelete` annotation. See the link:{userGuideBase}#soft-delete[User Guide] for details. +In previous versions, support for soft-deletes was somewhat implementable using +a combination of any or all of event-listeners, filters, `@Where`, etc. +Applications using such implementations are encouraged to switch. + + [[custom-tenant-identifier-type]] == Custom tenant identifier type diff --git a/release/src/release/announcement-template.adoc b/release/src/release/announcement-template.adoc index ea50f1732d..a294e7f17c 100644 --- a/release/src/release/announcement-template.adoc +++ b/release/src/release/announcement-template.adoc @@ -1,20 +1,56 @@ -:family: 6.3 -:version: 6.3.0.Final - = Hibernate {version} Steve Ebersole :awestruct-tags: ["Hibernate ORM", "Releases"] :awestruct-layout: blog-post + +:version: 6.4.0.CR1 +:family: 6.4 + :docs-url: https://docs.jboss.org/hibernate/orm/{family} :javadocs-url: {docs-url}/javadocs :migration-guide-url: {docs-url}/migration-guide/migration-guide.html :intro-guide-url: {docs-url}/introduction/html_single/Hibernate_Introduction.html :user-guide-url: {docs-url}/userguide/html_single/Hibernate_User_Guide.html -// Text ... +6.4 adds some cool new features, in addition to many improvements and fixes. + +[[soft-delete]] +== Soft Delete -== Conclusion +6.4 adds support for soft deletes using the new `@SoftDelete` annotation. + +[source,java] +---- +@Entity +@SoftDelete +class Account { + ... +} +---- + +Dealing with values as deleted/non-deleted versus active/inactive (reversed) is simple using an annotation attribute: + +This has the ability to easily handle active v. deleted tracking using a simple annotation attribute: + +[source,java] +---- +@Entity +@SoftDelete(strategy=ACTIVE) +class Account { + ... +} +---- + +It even supports pluggable converters for storing the indicator value into the database.strategy + +See the link:{userGuideBase}#soft-delete[User Guide] for details. + + + + + +== Finally, For additional details, see: