mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-02-16 08:05:05 +00:00
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
This commit is contained in:
parent
ae3c88ab66
commit
5b49d5efba
@ -23,7 +23,7 @@ Soft delete support is defined by 3 main parts -
|
|||||||
|
|
||||||
1. The <<soft-delete-column,column>> which contains the indicator.
|
1. The <<soft-delete-column,column>> which contains the indicator.
|
||||||
2. A <<soft-delete-conversion,conversion>> from `Boolean` indicator value to the proper database type
|
2. A <<soft-delete-conversion,conversion>> from `Boolean` indicator value to the proper database type
|
||||||
3. Whether to <<soft-delete-reverse,reverse>> the indicator values, tracking active/inactive instead
|
3. A <<soft-delete-type,strategy>> for interpreting the stored indicator values.
|
||||||
|
|
||||||
|
|
||||||
[[soft-delete-column]]
|
[[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.
|
The column where the indicator value is stored is defined using `@SoftDelete#columnName` attribute.
|
||||||
|
|
||||||
When using <<soft-delete-reverse,reversed>> mappings, the column name defaults to `active`; otherwise, it
|
The default column name depends on the <<soft-delete-type,strategy>> being used -
|
||||||
defaults to the name `deleted`.
|
|
||||||
|
ACTIVE::
|
||||||
|
The default column name is `active`.
|
||||||
|
DELETED::
|
||||||
|
The default column name is `deleted`.
|
||||||
|
|
||||||
See <<soft-delete-basic-example>> for an example of customizing the column name.
|
See <<soft-delete-basic-example>> 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]]
|
[[soft-delete-conversion]]
|
||||||
==== Indicator conversion
|
==== Indicator conversion
|
||||||
|
|
||||||
The conversion is defined using a JPA <<basic-jpa-convert,AttributeConverter>>. The "domain type" is always
|
The conversion is defined using a Jakarta Persistence <<basic-jpa-convert,AttributeConverter>>. The domain-type is always
|
||||||
`boolean`. The "relational type" can be any type, as defined by the converter; generally `BOOLEAN`, `BIT`, `INTEGER` or `CHAR`.
|
`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 <<soft-delete-basic-example>>
|
An explicit conversion can be specified using `@SoftDelete#converter`. See <<soft-delete-basic-example>>
|
||||||
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 -
|
Hibernate-provided converters for the 3 most common cases -
|
||||||
|
|
||||||
`NumericBooleanConverter`:: Defines conversion using `0` for `false` and `1` for `true`
|
`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`
|
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`
|
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 <<soft-delete-type,strategy>> used. Hibernate will handle applying the strategy.
|
||||||
|
|
||||||
|
|
||||||
[[soft-delete-entity]]
|
[[soft-delete-entity]]
|
||||||
==== Entity soft delete
|
==== 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.
|
entities and collections defined within the package.
|
||||||
|
|
||||||
|
|
||||||
[[soft-delete-reverse]]
|
[[soft-delete-type]]
|
||||||
==== Reversed soft delete
|
==== Strategy - SoftDeleteType
|
||||||
|
|
||||||
A common requirement in applications using soft delete is to track rows which are active as opposed to removed,
|
Given truth values, there are 2 valid ways to interpret the values stored in the database. This
|
||||||
reversing the boolean value. For example:
|
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]]
|
ACTIVE::
|
||||||
.Reversed soft-delete
|
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).
|
||||||
[source,java]
|
DELETED::
|
||||||
----
|
Tracks rows which are deleted. A `true` value in the database indicates that the row is deleted;
|
||||||
include::{testing-dir}/converter/reversed/TheEntity.java[tag=example-soft-delete-reverse, indent=0]
|
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.
|
|
@ -62,8 +62,7 @@
|
|||||||
/**
|
/**
|
||||||
* (Optional) The name of the column.
|
* (Optional) The name of the column.
|
||||||
* <p/>
|
* <p/>
|
||||||
* Default depends on {@linkplain #trackActive()} - {@code deleted} if {@code false} and
|
* Default depends on the {@linkplain #strategy() strategy} being used.
|
||||||
* {@code active} if {@code true}.
|
|
||||||
*
|
*
|
||||||
* @see SoftDeleteType#getDefaultColumnName()
|
* @see SoftDeleteType#getDefaultColumnName()
|
||||||
*/
|
*/
|
||||||
|
@ -19,20 +19,14 @@ earlier versions, see any other pertinent migration guides as well.
|
|||||||
[[soft-delete]]
|
[[soft-delete]]
|
||||||
== Soft Delete
|
== Soft Delete
|
||||||
|
|
||||||
6.4 adds support for soft deletes against an entity's primary table and collection tables, using the
|
6.4 adds support for soft deletes, using the new `@SoftDelete` annotation.
|
||||||
new `@SoftDelete` annotation.
|
|
||||||
|
|
||||||
[source,java]
|
|
||||||
----
|
|
||||||
@Entity
|
|
||||||
@SoftDelete
|
|
||||||
class Account {
|
|
||||||
...
|
|
||||||
}
|
|
||||||
----
|
|
||||||
|
|
||||||
See the link:{userGuideBase}#soft-delete[User Guide] for details.
|
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]]
|
||||||
== Custom tenant identifier type
|
== Custom tenant identifier type
|
||||||
|
|
||||||
|
@ -1,20 +1,56 @@
|
|||||||
:family: 6.3
|
|
||||||
:version: 6.3.0.Final
|
|
||||||
|
|
||||||
= Hibernate {version}
|
= Hibernate {version}
|
||||||
Steve Ebersole
|
Steve Ebersole
|
||||||
:awestruct-tags: ["Hibernate ORM", "Releases"]
|
:awestruct-tags: ["Hibernate ORM", "Releases"]
|
||||||
:awestruct-layout: blog-post
|
:awestruct-layout: blog-post
|
||||||
|
|
||||||
|
:version: 6.4.0.CR1
|
||||||
|
:family: 6.4
|
||||||
|
|
||||||
:docs-url: https://docs.jboss.org/hibernate/orm/{family}
|
:docs-url: https://docs.jboss.org/hibernate/orm/{family}
|
||||||
:javadocs-url: {docs-url}/javadocs
|
:javadocs-url: {docs-url}/javadocs
|
||||||
:migration-guide-url: {docs-url}/migration-guide/migration-guide.html
|
:migration-guide-url: {docs-url}/migration-guide/migration-guide.html
|
||||||
:intro-guide-url: {docs-url}/introduction/html_single/Hibernate_Introduction.html
|
:intro-guide-url: {docs-url}/introduction/html_single/Hibernate_Introduction.html
|
||||||
:user-guide-url: {docs-url}/userguide/html_single/Hibernate_User_Guide.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:
|
For additional details, see:
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user