5
5
package org .hibernate .boot .model .internal ;
6
6
7
7
import org .hibernate .annotations .SoftDelete ;
8
+ import org .hibernate .annotations .SoftDeleteType ;
8
9
import org .hibernate .boot .model .convert .internal .ClassBasedConverterDescriptor ;
9
10
import org .hibernate .boot .model .naming .Identifier ;
10
11
import org .hibernate .boot .model .naming .PhysicalNamingStrategy ;
11
12
import org .hibernate .boot .model .relational .Database ;
12
13
import org .hibernate .boot .spi .MetadataBuildingContext ;
13
- import org .hibernate .dialect .Dialect ;
14
14
import org .hibernate .mapping .BasicValue ;
15
15
import org .hibernate .mapping .Column ;
16
16
import org .hibernate .mapping .SoftDeletable ;
17
17
import org .hibernate .mapping .Table ;
18
+ import org .hibernate .metamodel .UnsupportedMappingException ;
18
19
import org .hibernate .metamodel .mapping .SoftDeletableModelPart ;
19
- import org .hibernate .metamodel .mapping .SoftDeleteMapping ;
20
20
import org .hibernate .metamodel .mapping .internal .MappingModelCreationProcess ;
21
21
import org .hibernate .metamodel .mapping .internal .SoftDeleteMappingImpl ;
22
- import org .hibernate .sql .ast .spi .SqlExpressionResolver ;
23
- import org .hibernate .sql .ast .tree .expression .ColumnReference ;
24
- import org .hibernate .sql .ast .tree .expression .Expression ;
25
- import org .hibernate .sql .ast .tree .expression .JdbcLiteral ;
26
- import org .hibernate .sql .ast .tree .from .TableReference ;
27
- import org .hibernate .sql .ast .tree .predicate .ComparisonPredicate ;
28
- import org .hibernate .sql .ast .tree .predicate .Predicate ;
29
- import org .hibernate .sql .ast .tree .update .Assignment ;
30
- import org .hibernate .type .descriptor .converter .spi .BasicValueConverter ;
31
- import org .hibernate .type .descriptor .jdbc .JdbcLiteralFormatter ;
22
+
23
+ import java .time .Instant ;
32
24
33
25
import static org .hibernate .internal .util .StringHelper .coalesce ;
34
26
import static org .hibernate .internal .util .StringHelper .isBlank ;
35
- import static org .hibernate .query .sqm .ComparisonOperator .EQUAL ;
36
27
37
28
/**
38
29
* Helper for dealing with {@link org.hibernate.annotations.SoftDelete}
@@ -62,22 +53,35 @@ public static void bindSoftDeleteIndicator(
62
53
context
63
54
);
64
55
table .addColumn ( softDeleteIndicatorColumn );
65
- target .enableSoftDelete ( softDeleteIndicatorColumn );
56
+ target .enableSoftDelete ( softDeleteIndicatorColumn , softDeleteConfig . strategy () );
66
57
}
67
58
68
59
private static BasicValue createSoftDeleteIndicatorValue (
69
60
SoftDelete softDeleteConfig ,
70
61
Table table ,
71
62
MetadataBuildingContext context ) {
72
- final ClassBasedConverterDescriptor converterDescriptor = new ClassBasedConverterDescriptor (
73
- softDeleteConfig .converter (),
74
- context .getBootstrapContext ().getClassmateContext ()
75
- );
76
-
77
63
final BasicValue softDeleteIndicatorValue = new BasicValue ( context , table );
78
64
softDeleteIndicatorValue .makeSoftDelete ( softDeleteConfig .strategy () );
79
- softDeleteIndicatorValue .setJpaAttributeConverterDescriptor ( converterDescriptor );
80
- softDeleteIndicatorValue .setImplicitJavaTypeAccess ( (typeConfiguration ) -> converterDescriptor .getRelationalValueResolvedType ().getErasedType () );
65
+
66
+ if ( softDeleteConfig .strategy () == SoftDeleteType .TIMESTAMP ) {
67
+ if ( softDeleteConfig .converter () != SoftDelete .UnspecifiedConversion .class ) {
68
+ throw new UnsupportedMappingException (
69
+ "Specifying SoftDelete#converter in conjunction with SoftDeleteType.TIMESTAMP is not supported"
70
+ );
71
+ }
72
+ softDeleteIndicatorValue .setImplicitJavaTypeAccess ( (typeConfiguration ) -> Instant .class );
73
+ }
74
+ else {
75
+ final ClassBasedConverterDescriptor converterDescriptor = new ClassBasedConverterDescriptor (
76
+ softDeleteConfig .converter (),
77
+ context .getBootstrapContext ().getClassmateContext ()
78
+ );
79
+ softDeleteIndicatorValue .setJpaAttributeConverterDescriptor ( converterDescriptor );
80
+ softDeleteIndicatorValue .setImplicitJavaTypeAccess (
81
+ (typeConfiguration ) -> converterDescriptor .getRelationalValueResolvedType ().getErasedType ()
82
+ );
83
+ }
84
+
81
85
return softDeleteIndicatorValue ;
82
86
}
83
87
@@ -87,11 +91,11 @@ private static Column createSoftDeleteIndicatorColumn(
87
91
MetadataBuildingContext context ) {
88
92
final Column softDeleteColumn = new Column ();
89
93
94
+ softDeleteColumn .setValue ( softDeleteIndicatorValue );
95
+ softDeleteIndicatorValue .addColumn ( softDeleteColumn );
96
+
90
97
applyColumnName ( softDeleteColumn , softDeleteConfig , context );
91
98
92
- softDeleteColumn .setLength ( 1 );
93
- softDeleteColumn .setNullable ( false );
94
- softDeleteColumn .setUnique ( false );
95
99
softDeleteColumn .setOptions ( softDeleteConfig .options () );
96
100
if ( isBlank ( softDeleteConfig .comment () ) ) {
97
101
softDeleteColumn .setComment ( "Soft-delete indicator" );
@@ -100,8 +104,15 @@ private static Column createSoftDeleteIndicatorColumn(
100
104
softDeleteColumn .setComment ( softDeleteConfig .comment () );
101
105
}
102
106
103
- softDeleteColumn .setValue ( softDeleteIndicatorValue );
104
- softDeleteIndicatorValue .addColumn ( softDeleteColumn );
107
+ softDeleteColumn .setUnique ( false );
108
+
109
+ if ( softDeleteConfig .strategy () == SoftDeleteType .TIMESTAMP ) {
110
+ softDeleteColumn .setNullable ( true );
111
+ }
112
+ else {
113
+ softDeleteColumn .setLength ( 1 );
114
+ softDeleteColumn .setNullable ( false );
115
+ }
105
116
106
117
return softDeleteColumn ;
107
118
}
@@ -112,6 +123,7 @@ private static void applyColumnName(
112
123
MetadataBuildingContext context ) {
113
124
final Database database = context .getMetadataCollector ().getDatabase ();
114
125
final PhysicalNamingStrategy namingStrategy = context .getBuildingOptions ().getPhysicalNamingStrategy ();
126
+ // NOTE : the argument order is strange here - the fallback value comes first
115
127
final String logicalColumnName = coalesce (
116
128
softDeleteConfig .strategy ().getDefaultColumnName (),
117
129
softDeleteConfig .columnName ()
@@ -128,105 +140,10 @@ public static SoftDeleteMappingImpl resolveSoftDeleteMapping(
128
140
SoftDeletable bootMapping ,
129
141
String tableName ,
130
142
MappingModelCreationProcess creationProcess ) {
131
- return resolveSoftDeleteMapping (
132
- softDeletableModelPart ,
133
- bootMapping ,
134
- tableName ,
135
- creationProcess .getCreationContext ().getDialect ()
136
- );
137
- }
138
-
139
- public static SoftDeleteMappingImpl resolveSoftDeleteMapping (
140
- SoftDeletableModelPart softDeletableModelPart ,
141
- SoftDeletable bootMapping ,
142
- String tableName ,
143
- Dialect dialect ) {
144
- final Column softDeleteColumn = bootMapping .getSoftDeleteColumn ();
145
- if ( softDeleteColumn == null ) {
143
+ if ( bootMapping .getSoftDeleteColumn () == null ) {
146
144
return null ;
147
145
}
148
-
149
- final BasicValue columnValue = (BasicValue ) softDeleteColumn .getValue ();
150
- final BasicValue .Resolution <?> resolution = columnValue .resolve ();
151
- //noinspection unchecked
152
- final BasicValueConverter <Boolean , Object > converter = (BasicValueConverter <Boolean , Object >) resolution .getValueConverter ();
153
- //noinspection unchecked
154
- final JdbcLiteralFormatter <Object > literalFormatter = resolution .getJdbcMapping ().getJdbcLiteralFormatter ();
155
-
156
- final Object deletedLiteralValue ;
157
- final Object nonDeletedLiteralValue ;
158
- if ( converter == null ) {
159
- // the database column is BIT or BOOLEAN : pass-thru
160
- deletedLiteralValue = true ;
161
- nonDeletedLiteralValue = false ;
162
- }
163
- else {
164
- deletedLiteralValue = converter .toRelationalValue ( true );
165
- nonDeletedLiteralValue = converter .toRelationalValue ( false );
166
- }
167
-
168
- return new SoftDeleteMappingImpl (
169
- softDeletableModelPart ,
170
- softDeleteColumn .getName (),
171
- tableName ,
172
- deletedLiteralValue ,
173
- literalFormatter .toJdbcLiteral ( deletedLiteralValue , dialect , null ),
174
- nonDeletedLiteralValue ,
175
- literalFormatter .toJdbcLiteral ( nonDeletedLiteralValue , dialect , null ),
176
- resolution .getJdbcMapping ()
177
- );
178
- }
179
-
180
- /**
181
- * Create a SQL AST Predicate for restricting matches to non-deleted rows
182
- *
183
- * @param tableReference The table reference for the table containing the soft-delete column
184
- * @param softDeleteMapping The soft-delete mapping
185
- */
186
- public static Predicate createNonSoftDeletedRestriction (
187
- TableReference tableReference ,
188
- SoftDeleteMapping softDeleteMapping ) {
189
- final ColumnReference softDeleteColumn = new ColumnReference ( tableReference , softDeleteMapping );
190
- final JdbcLiteral <?> notDeletedLiteral = new JdbcLiteral <>(
191
- softDeleteMapping .getNonDeletedLiteralValue (),
192
- softDeleteMapping .getJdbcMapping ()
193
- );
194
- return new ComparisonPredicate ( softDeleteColumn , EQUAL , notDeletedLiteral );
195
- }
196
-
197
- /**
198
- * Create a SQL AST Predicate for restricting matches to non-deleted rows
199
- *
200
- * @param tableReference The table reference for the table containing the soft-delete column
201
- * @param softDeleteMapping The soft-delete mapping
202
- */
203
- public static Predicate createNonSoftDeletedRestriction (
204
- TableReference tableReference ,
205
- SoftDeleteMapping softDeleteMapping ,
206
- SqlExpressionResolver expressionResolver ) {
207
- final Expression softDeleteColumn = expressionResolver .resolveSqlExpression ( tableReference , softDeleteMapping );
208
- final JdbcLiteral <?> notDeletedLiteral = new JdbcLiteral <>(
209
- softDeleteMapping .getNonDeletedLiteralValue (),
210
- softDeleteMapping .getJdbcMapping ()
211
- );
212
- return new ComparisonPredicate ( softDeleteColumn , EQUAL , notDeletedLiteral );
146
+ return new SoftDeleteMappingImpl ( softDeletableModelPart , bootMapping , tableName , creationProcess );
213
147
}
214
148
215
- /**
216
- * Create a SQL AST Assignment for setting the soft-delete column to its
217
- * deleted indicate value
218
- *
219
- * @param tableReference The table reference for the table containing the soft-delete column
220
- * @param softDeleteMapping The soft-delete mapping
221
- */
222
- public static Assignment createSoftDeleteAssignment (
223
- TableReference tableReference ,
224
- SoftDeleteMapping softDeleteMapping ) {
225
- final ColumnReference softDeleteColumn = new ColumnReference ( tableReference , softDeleteMapping );
226
- final JdbcLiteral <?> softDeleteIndicator = new JdbcLiteral <>(
227
- softDeleteMapping .getDeletedLiteralValue (),
228
- softDeleteMapping .getJdbcMapping ()
229
- );
230
- return new Assignment ( softDeleteColumn , softDeleteIndicator );
231
- }
232
149
}
0 commit comments