Skip to content

Commit e1808bd

Browse files
committed
HHH-17325 - @softdelete with timestamp
1 parent e6451ac commit e1808bd

23 files changed

+502
-60
lines changed

hibernate-core/src/main/java/org/hibernate/boot/model/internal/SoftDeleteHelper.java

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import org.hibernate.mapping.Column;
1616
import org.hibernate.mapping.SoftDeletable;
1717
import org.hibernate.mapping.Table;
18+
import org.hibernate.metamodel.UnsupportedMappingException;
1819
import org.hibernate.metamodel.mapping.SoftDeletableModelPart;
1920
import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess;
2021
import org.hibernate.metamodel.mapping.internal.SoftDeleteMappingImpl;
@@ -63,6 +64,11 @@ private static BasicValue createSoftDeleteIndicatorValue(
6364
softDeleteIndicatorValue.makeSoftDelete( softDeleteConfig.strategy() );
6465

6566
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+
}
6672
softDeleteIndicatorValue.setImplicitJavaTypeAccess( (typeConfiguration) -> Instant.class );
6773
}
6874
else {
@@ -90,9 +96,6 @@ private static Column createSoftDeleteIndicatorColumn(
9096

9197
applyColumnName( softDeleteColumn, softDeleteConfig, context );
9298

93-
softDeleteColumn.setLength( 1 );
94-
softDeleteColumn.setNullable( false );
95-
softDeleteColumn.setUnique( false );
9699
softDeleteColumn.setOptions( softDeleteConfig.options() );
97100
if ( isBlank( softDeleteConfig.comment() ) ) {
98101
softDeleteColumn.setComment( "Soft-delete indicator" );
@@ -101,6 +104,16 @@ private static Column createSoftDeleteIndicatorColumn(
101104
softDeleteColumn.setComment( softDeleteConfig.comment() );
102105
}
103106

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+
}
116+
104117
return softDeleteColumn;
105118
}
106119

hibernate-core/src/main/java/org/hibernate/metamodel/mapping/SoftDeletableModelPart.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,8 @@ public interface SoftDeletableModelPart extends ModelPartContainer {
1515
*/
1616
SoftDeleteMapping getSoftDeleteMapping();
1717

18+
/**
19+
* Details about the table which holds the soft-delete column.
20+
*/
1821
TableDetails getSoftDeleteTableDetails();
1922
}

hibernate-core/src/main/java/org/hibernate/metamodel/mapping/SoftDeleteMapping.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ public interface SoftDeleteMapping extends SelectableMapping, VirtualModelPart,
8282
ColumnValueBinding createDeletedValueBinding(ColumnReference softDeleteColumnReference);
8383

8484
void applyNonDeletedRestriction(RestrictedTableMutationBuilder<?, ?> tableMutationBuilder);
85-
void applyDeletedAssignment(ColumnValuesTableMutationBuilder tableMutationBuilder);
85+
void applyDeletedAssignment(ColumnValuesTableMutationBuilder<?> tableMutationBuilder);
86+
void applyNonDeletedAssignment(ColumnValuesTableMutationBuilder<?> tableMutationBuilder);
8687

8788

8889
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/SoftDeleteMappingImpl.java

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -220,8 +220,11 @@ public Predicate createNonDeletedRestriction(TableReference tableReference, SqlE
220220
public ColumnValueBinding createNonDeletedValueBinding(ColumnReference softDeleteColumnReference) {
221221
final ColumnWriteFragment nonDeletedFragment;
222222
if ( strategy == SoftDeleteType.TIMESTAMP ) {
223-
// return new ColumnValueBinding( softDeleteColumnReference, null );
224-
throw new UnsupportedOperationException( );
223+
nonDeletedFragment = new ColumnWriteFragment(
224+
null,
225+
Collections.emptyList(),
226+
jdbcMapping
227+
);
225228
}
226229
else {
227230
nonDeletedFragment = new ColumnWriteFragment(
@@ -237,12 +240,11 @@ public ColumnValueBinding createNonDeletedValueBinding(ColumnReference softDelet
237240
public ColumnValueBinding createDeletedValueBinding(ColumnReference softDeleteColumnReference) {
238241
final ColumnWriteFragment deletedFragment;
239242
if ( strategy == SoftDeleteType.TIMESTAMP ) {
240-
// deletedFragment = new ColumnWriteFragment(
241-
// currentTimestampFunctionName,
242-
// Collections.emptyList(),
243-
// getJdbcMapping()
244-
// );
245-
throw new UnsupportedOperationException( );
243+
deletedFragment = new ColumnWriteFragment(
244+
currentTimestampFunctionName,
245+
Collections.emptyList(),
246+
getJdbcMapping()
247+
);
246248
}
247249
else {
248250
deletedFragment = new ColumnWriteFragment(
@@ -269,7 +271,7 @@ public void applyNonDeletedRestriction(RestrictedTableMutationBuilder<?, ?> tabl
269271
}
270272

271273
@Override
272-
public void applyDeletedAssignment(ColumnValuesTableMutationBuilder tableMutationBuilder) {
274+
public void applyDeletedAssignment(ColumnValuesTableMutationBuilder<?> tableMutationBuilder) {
273275
if ( strategy == SoftDeleteType.TIMESTAMP ) {
274276
tableMutationBuilder.addValueColumn( getColumnName(), currentTimestampFunctionName, getJdbcMapping() );
275277
}
@@ -278,6 +280,21 @@ public void applyDeletedAssignment(ColumnValuesTableMutationBuilder tableMutatio
278280
}
279281
}
280282

283+
@Override
284+
public void applyNonDeletedAssignment(ColumnValuesTableMutationBuilder<?> tableMutationBuilder) {
285+
if ( strategy == SoftDeleteType.TIMESTAMP ) {
286+
final ColumnReference columnReference = new ColumnReference(
287+
tableMutationBuilder.getMutatingTable(),
288+
this
289+
);
290+
final ColumnValueBinding nonDeletedValueBinding = createNonDeletedValueBinding( columnReference );
291+
tableMutationBuilder.addValueColumn( nonDeletedValueBinding );
292+
}
293+
else {
294+
tableMutationBuilder.addValueColumn( getColumnName(), nonDeletedLiteralText, getJdbcMapping() );
295+
}
296+
}
297+
281298
@Override
282299
public JdbcMapping getJdbcMapping() {
283300
return jdbcMapping;

hibernate-core/src/main/java/org/hibernate/persister/collection/BasicCollectionPersister.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -223,16 +223,14 @@ public RestrictedTableMutation<JdbcMutationOperation> generateDeleteAllAst(Mutat
223223
final ColumnReference softDeleteColumn = new ColumnReference( tableReference, softDeleteMapping );
224224
final ColumnValueBinding nonDeletedBinding = softDeleteMapping.createNonDeletedValueBinding( softDeleteColumn );
225225
final ColumnValueBinding deletedBinding = softDeleteMapping.createDeletedValueBinding( softDeleteColumn );
226-
restrictionBindings.add( nonDeletedBinding );
227-
final List<ColumnValueBinding> valueBindings = List.of( deletedBinding );
228226

229227
return new TableUpdateStandard(
230228
tableReference,
231229
this,
232230
"soft-delete removal",
233-
valueBindings,
231+
List.of( deletedBinding ),
234232
restrictionBindings,
235-
null
233+
List.of( nonDeletedBinding )
236234
);
237235
}
238236

@@ -329,7 +327,7 @@ else if ( indexDescriptor != null ) {
329327

330328
final SoftDeleteMapping softDeleteMapping = getAttributeMapping().getSoftDeleteMapping();
331329
if ( softDeleteMapping != null ) {
332-
insertBuilder.addValueColumn( softDeleteMapping );
330+
softDeleteMapping.applyNonDeletedAssignment( insertBuilder );
333331
}
334332
}
335333

hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3458,7 +3458,7 @@ public void addDiscriminatorToInsertGroup(MutationGroupBuilder insertGroupBuilde
34583458
public void addSoftDeleteToInsertGroup(MutationGroupBuilder insertGroupBuilder) {
34593459
if ( softDeleteMapping != null ) {
34603460
final TableInsertBuilder insertBuilder = insertGroupBuilder.getTableDetailsBuilder( getIdentifierTableName() );
3461-
insertBuilder.addValueColumn( softDeleteMapping );
3461+
softDeleteMapping.applyNonDeletedAssignment( insertBuilder );
34623462
}
34633463
}
34643464

hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8954,7 +8954,8 @@ private void visitTableUpdate(RestrictedTableMutation<? extends MutationOperatio
89548954
tableUpdate.forEachOptimisticLockBinding( (position, columnValueBinding) -> {
89558955
sqlBuffer.append( " and " );
89568956
sqlBuffer.append( columnValueBinding.getColumnReference().getColumnExpression() );
8957-
if ( columnValueBinding.getValueExpression() == null ) {
8957+
if ( columnValueBinding.getValueExpression() == null
8958+
|| columnValueBinding.getValueExpression().getFragment() == null ) {
89588959
sqlBuffer.append( " is null" );
89598960
}
89608961
else {

hibernate-core/src/main/java/org/hibernate/sql/model/ast/ColumnValueBinding.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,9 @@
99
import org.hibernate.sql.ast.tree.expression.ColumnReference;
1010

1111
/**
12-
* Represents the binding of a value to a column. Can be used to
13-
* uniformly model value assignments wrt inserts, updates and upserts.
14-
*
15-
* @apiNote Practically speaking, the {@linkplain #getValueExpression() value}
16-
* can only be a JDBC parameter or a literal.
12+
* Represents the binding of a value to a column. Uniformly
13+
* models both value assignments and value restrictions in
14+
* relation to inserts, updates and upserts.
1715
*
1816
* @author Steve Ebersole
1917
*/

hibernate-core/src/main/java/org/hibernate/sql/model/ast/ColumnWriteFragment.java

Lines changed: 26 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616

1717
/**
1818
* Models a column's value expression within the SQL AST. Used to model:<ul>
19-
* <li>a column's new value in a SET clause</li>
20-
* <li>a column's old value in a restriction (optimistic locking)</li>
19+
* <li>a column's new value (UPDATE SET clause or INSERT VALUES clause)</li>
20+
* <li>a column's old value in a restriction (optimistic locking, etc.)</li>
2121
* </ul>
2222
*
2323
* @see ColumnTransformer#write()
@@ -64,32 +64,29 @@ public void accept(SqlAstWalker sqlTreeWalker) {
6464

6565
@Override
6666
public String toString() {
67-
switch ( parameters.size() ) {
68-
case 0:
69-
return String.format(
70-
Locale.ROOT,
71-
"ColumnWriteFragment(%s)@%s",
72-
fragment,
73-
hashCode()
74-
);
75-
case 1:
76-
return String.format(
77-
Locale.ROOT,
78-
"ColumnWriteFragment(%s = %s (%s))@%s",
79-
parameters.get( 0 ).getColumnReference().getColumnExpression(),
80-
fragment,
81-
parameters.get( 0 ).getUsage(),
82-
hashCode()
83-
);
84-
default:
85-
return String.format(
86-
Locale.ROOT,
87-
"ColumnWriteFragment(%s = %s (%s))@%s",
88-
parameters,
89-
fragment,
90-
parameters.get( 0 ).getUsage(),
91-
hashCode()
92-
);
93-
}
67+
return switch ( parameters.size() ) {
68+
case 0 -> String.format(
69+
Locale.ROOT,
70+
"ColumnWriteFragment(%s)@%s",
71+
fragment,
72+
hashCode()
73+
);
74+
case 1 -> String.format(
75+
Locale.ROOT,
76+
"ColumnWriteFragment(%s = %s (%s))@%s",
77+
parameters.get( 0 ).getColumnReference().getColumnExpression(),
78+
fragment,
79+
parameters.get( 0 ).getUsage(),
80+
hashCode()
81+
);
82+
default -> String.format(
83+
Locale.ROOT,
84+
"ColumnWriteFragment(%s = %s (%s))@%s",
85+
parameters,
86+
fragment,
87+
parameters.get( 0 ).getUsage(),
88+
hashCode()
89+
);
90+
};
9491
}
9592
}

hibernate-core/src/main/java/org/hibernate/sql/model/ast/builder/AbstractTableInsertBuilder.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,11 @@ public void addValueColumn(String columnName, String columnWriteFragment, JdbcMa
8181
}
8282
}
8383

84+
@Override
85+
public void addValueColumn(ColumnValueBinding valueBinding) {
86+
valueBindingList.add( valueBinding );
87+
}
88+
8489
@Override
8590
public void addKeyColumn(String columnName, String columnWriteFragment, JdbcMapping jdbcMapping) {
8691
addColumn( columnName, columnWriteFragment, jdbcMapping, keyBindingList );

0 commit comments

Comments
 (0)