From 2273365e06ef1310be96543cae436aec698bc782 Mon Sep 17 00:00:00 2001 From: Steve Ebersole Date: Wed, 31 Jul 2024 14:21:25 -0500 Subject: [PATCH] HHH-17448 - Add newly standard column annotation attributes to Hibernate column annotations --- .../org/hibernate/annotations/SoftDelete.java | 18 +++++++ .../boot/model/internal/SoftDeleteHelper.java | 9 +++- .../internal/SoftDeleteAnnotation.java | 23 +++++++++ .../SoftDeleteColumnConfigTests.java | 51 +++++++++++++++++++ .../testing/schema/SchemaCreateHelper.java | 19 +++++++ 5 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/softdelete/SoftDeleteColumnConfigTests.java 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 05f49092f4..0c6b9e76dc 100644 --- a/hibernate-core/src/main/java/org/hibernate/annotations/SoftDelete.java +++ b/hibernate-core/src/main/java/org/hibernate/annotations/SoftDelete.java @@ -68,6 +68,24 @@ public @interface SoftDelete { */ String columnName() default ""; + /** + * (Optional) The SQL fragment that is used when + * generating the DDL for the column. + *

+ * The DDL must be written in the native SQL dialect + * of the target database (it is not portable across databases). + * + * @since 7.0 + */ + String options() default ""; + + /** + * (Optional) A comment to be applied to the column. + * + * @since 7.0 + */ + String comment() default ""; + /** * The strategy to use for storing/reading values to/from the database. *

diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/SoftDeleteHelper.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/SoftDeleteHelper.java index a075a20979..ba89a07ef3 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/SoftDeleteHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/SoftDeleteHelper.java @@ -13,6 +13,7 @@ import org.hibernate.boot.model.naming.PhysicalNamingStrategy; import org.hibernate.boot.model.relational.Database; import org.hibernate.boot.spi.MetadataBuildingContext; import org.hibernate.dialect.Dialect; +import org.hibernate.internal.util.StringHelper; import org.hibernate.mapping.BasicValue; import org.hibernate.mapping.Column; import org.hibernate.mapping.SoftDeletable; @@ -93,7 +94,13 @@ public class SoftDeleteHelper { softDeleteColumn.setLength( 1 ); softDeleteColumn.setNullable( false ); softDeleteColumn.setUnique( false ); - softDeleteColumn.setComment( "Soft-delete indicator" ); + softDeleteColumn.setOptions( softDeleteConfig.options() ); + if ( StringHelper.isEmpty( softDeleteConfig.comment() ) ) { + softDeleteColumn.setComment( "Soft-delete indicator" ); + } + else { + softDeleteColumn.setComment( softDeleteConfig.comment() ); + } softDeleteColumn.setValue( softDeleteIndicatorValue ); softDeleteIndicatorValue.addColumn( softDeleteColumn ); diff --git a/hibernate-core/src/main/java/org/hibernate/boot/models/annotations/internal/SoftDeleteAnnotation.java b/hibernate-core/src/main/java/org/hibernate/boot/models/annotations/internal/SoftDeleteAnnotation.java index 8c63b3ab45..631ca1a801 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/models/annotations/internal/SoftDeleteAnnotation.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/models/annotations/internal/SoftDeleteAnnotation.java @@ -20,6 +20,8 @@ import static org.hibernate.boot.models.internal.OrmAnnotationHelper.extractJand @jakarta.annotation.Generated("org.hibernate.orm.build.annotations.ClassGeneratorProcessor") public class SoftDeleteAnnotation implements SoftDelete { private String columnName; + private String options; + private String comment; private org.hibernate.annotations.SoftDeleteType strategy; private java.lang.Class> converter; @@ -38,6 +40,8 @@ public class SoftDeleteAnnotation implements SoftDelete { public SoftDeleteAnnotation(SoftDelete annotation, SourceModelBuildingContext modelContext) { this.columnName = annotation.columnName(); this.strategy = annotation.strategy(); + this.options = annotation.options(); + this.comment = annotation.comment(); this.converter = annotation.converter(); } @@ -52,6 +56,8 @@ public class SoftDeleteAnnotation implements SoftDelete { modelContext ); this.strategy = extractJandexValue( annotation, HibernateAnnotations.SOFT_DELETE, "strategy", modelContext ); + this.options = extractJandexValue( annotation, HibernateAnnotations.SOFT_DELETE, "options", modelContext ); + this.comment = extractJandexValue( annotation, HibernateAnnotations.SOFT_DELETE, "comment", modelContext ); this.converter = extractJandexValue( annotation, HibernateAnnotations.SOFT_DELETE, "converter", modelContext ); } @@ -69,6 +75,23 @@ public class SoftDeleteAnnotation implements SoftDelete { this.columnName = value; } + @Override + public String options() { + return options; + } + + public void options(String options) { + this.options = options; + } + + @Override + public String comment() { + return comment; + } + + public void comment(String comment) { + this.comment = comment; + } @Override public org.hibernate.annotations.SoftDeleteType strategy() { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/softdelete/SoftDeleteColumnConfigTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/softdelete/SoftDeleteColumnConfigTests.java new file mode 100644 index 0000000000..033033df45 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/softdelete/SoftDeleteColumnConfigTests.java @@ -0,0 +1,51 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html. + */ +package org.hibernate.orm.test.softdelete; + +import org.hibernate.annotations.SoftDelete; +import org.hibernate.mapping.Column; +import org.hibernate.mapping.PersistentClass; +import org.hibernate.mapping.RootClass; + +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.DomainModelScope; +import org.hibernate.testing.schema.SchemaCreateHelper; +import org.junit.jupiter.api.Test; + +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Steve Ebersole + */ +@SuppressWarnings("JUnitMalformedDeclaration") +public class SoftDeleteColumnConfigTests { + @Test + @DomainModel(annotatedClasses = Thing.class) + void verifyModel(DomainModelScope modelScope) { + final RootClass entityBinding = (RootClass) modelScope.getEntityBinding( Thing.class ); + final Column softDeleteColumn = entityBinding.getSoftDeleteColumn(); + assertThat( softDeleteColumn.getOptions() ).isEqualTo( "do_it=true" ); + assertThat( softDeleteColumn.getComment() ).isEqualTo( "Explicit soft-delete comment" ); + + final String ddl = SchemaCreateHelper.toCreateDdl( modelScope.getDomainModel() ); + assertThat( ddl ).contains( "do_it=true" ); + assertThat( ddl ).contains( "Explicit soft-delete comment" ); + } + + @Entity(name="Thing") + @Table(name="Thing") + @SoftDelete( comment = "Explicit soft-delete comment", options = "do_it=true" ) + public static class Thing { + @Id + private Integer id; + private String name; + } +} diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/schema/SchemaCreateHelper.java b/hibernate-testing/src/main/java/org/hibernate/testing/schema/SchemaCreateHelper.java index 8e6ea31c13..0795bbc8d2 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/schema/SchemaCreateHelper.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/schema/SchemaCreateHelper.java @@ -7,6 +7,7 @@ package org.hibernate.testing.schema; import java.io.OutputStreamWriter; +import java.io.StringWriter; import java.io.Writer; import java.sql.Connection; import java.util.HashMap; @@ -80,6 +81,24 @@ public class SchemaCreateHelper { ); } + public static String toCreateDdl(Metadata metadata) { + final StringWriter writer = new StringWriter(); + + final ServiceRegistry serviceRegistry = ( (MetadataImplementor) metadata ).getMetadataBuildingOptions().getServiceRegistry(); + final Map settings = serviceRegistry.requireService( ConfigurationService.class ).getSettings(); + final Map copy = new HashMap<>( settings ); + copy.put( SchemaToolingSettings.JAKARTA_HBM2DDL_SCRIPTS_ACTION, Action.CREATE_ONLY ); + copy.put( SchemaToolingSettings.JAKARTA_HBM2DDL_SCRIPTS_CREATE_TARGET, writer ); + SchemaManagementToolCoordinator.process( + metadata, + serviceRegistry, + copy, + DelayedDropRegistryNotAvailableImpl.INSTANCE + ); + + return writer.toString(); + } + @AllowSysOut public static void createOnlyToStdOut(Metadata metadata, ServiceRegistry serviceRegistry) { createOnlyToWriter( metadata, serviceRegistry, new OutputStreamWriter( System.out ) );