55package  org .hibernate .boot .model .internal ;
66
77import  org .hibernate .annotations .SoftDelete ;
8+ import  org .hibernate .annotations .SoftDeleteType ;
89import  org .hibernate .boot .model .convert .internal .ClassBasedConverterDescriptor ;
910import  org .hibernate .boot .model .naming .Identifier ;
1011import  org .hibernate .boot .model .naming .PhysicalNamingStrategy ;
1112import  org .hibernate .boot .model .relational .Database ;
1213import  org .hibernate .boot .spi .MetadataBuildingContext ;
13- import  org .hibernate .dialect .Dialect ;
1414import  org .hibernate .mapping .BasicValue ;
1515import  org .hibernate .mapping .Column ;
1616import  org .hibernate .mapping .SoftDeletable ;
1717import  org .hibernate .mapping .Table ;
18+ import  org .hibernate .metamodel .UnsupportedMappingException ;
1819import  org .hibernate .metamodel .mapping .SoftDeletableModelPart ;
19- import  org .hibernate .metamodel .mapping .SoftDeleteMapping ;
2020import  org .hibernate .metamodel .mapping .internal .MappingModelCreationProcess ;
2121import  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 ;
3224
3325import  static  org .hibernate .internal .util .StringHelper .coalesce ;
3426import  static  org .hibernate .internal .util .StringHelper .isBlank ;
35- import  static  org .hibernate .query .sqm .ComparisonOperator .EQUAL ;
3627
3728/** 
3829 * Helper for dealing with {@link org.hibernate.annotations.SoftDelete} 
@@ -62,22 +53,35 @@ public static void bindSoftDeleteIndicator(
6253				context 
6354		);
6455		table .addColumn ( softDeleteIndicatorColumn  );
65- 		target .enableSoftDelete ( softDeleteIndicatorColumn  );
56+ 		target .enableSoftDelete ( softDeleteIndicatorColumn ,  softDeleteConfig . strategy ()  );
6657	}
6758
6859	private  static  BasicValue  createSoftDeleteIndicatorValue (
6960			SoftDelete  softDeleteConfig ,
7061			Table  table ,
7162			MetadataBuildingContext  context ) {
72- 		final  ClassBasedConverterDescriptor  converterDescriptor  = new  ClassBasedConverterDescriptor (
73- 				softDeleteConfig .converter (),
74- 				context .getBootstrapContext ().getClassmateContext ()
75- 		);
76- 
7763		final  BasicValue  softDeleteIndicatorValue  = new  BasicValue ( context , table  );
7864		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+ 
8185		return  softDeleteIndicatorValue ;
8286	}
8387
@@ -87,11 +91,11 @@ private static Column createSoftDeleteIndicatorColumn(
8791			MetadataBuildingContext  context ) {
8892		final  Column  softDeleteColumn  = new  Column ();
8993
94+ 		softDeleteColumn .setValue ( softDeleteIndicatorValue  );
95+ 		softDeleteIndicatorValue .addColumn ( softDeleteColumn  );
96+ 
9097		applyColumnName ( softDeleteColumn , softDeleteConfig , context  );
9198
92- 		softDeleteColumn .setLength ( 1  );
93- 		softDeleteColumn .setNullable ( false  );
94- 		softDeleteColumn .setUnique ( false  );
9599		softDeleteColumn .setOptions ( softDeleteConfig .options () );
96100		if  ( isBlank ( softDeleteConfig .comment () ) ) {
97101			softDeleteColumn .setComment ( "Soft-delete indicator"  );
@@ -100,8 +104,15 @@ private static Column createSoftDeleteIndicatorColumn(
100104			softDeleteColumn .setComment ( softDeleteConfig .comment () );
101105		}
102106
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+ 		}
105116
106117		return  softDeleteColumn ;
107118	}
@@ -112,6 +123,7 @@ private static void applyColumnName(
112123			MetadataBuildingContext  context ) {
113124		final  Database  database  = context .getMetadataCollector ().getDatabase ();
114125		final  PhysicalNamingStrategy  namingStrategy  = context .getBuildingOptions ().getPhysicalNamingStrategy ();
126+ 		// NOTE : the argument order is strange here - the fallback value comes first 
115127		final  String  logicalColumnName  = coalesce (
116128				softDeleteConfig .strategy ().getDefaultColumnName (),
117129				softDeleteConfig .columnName ()
@@ -128,105 +140,10 @@ public static SoftDeleteMappingImpl resolveSoftDeleteMapping(
128140			SoftDeletable  bootMapping ,
129141			String  tableName ,
130142			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  ) {
146144			return  null ;
147145		}
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  );
213147	}
214148
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- 	}
232149}
0 commit comments