Skip to content

Commit 8baef74

Browse files
committed
HHH-4396 - Ability to patternize embedded column names
1 parent 0d56845 commit 8baef74

File tree

4 files changed

+100
-17
lines changed

4 files changed

+100
-17
lines changed

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

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -351,38 +351,38 @@ public void redefineColumnName(String columnName, String propertyName, boolean a
351351
final String inferredColumnName = inferColumnName( propertyName );
352352
String realColumnName = inferredColumnName;
353353
if ( parent.getPropertyHolder().isComponent() ) {
354-
// find the pattern if there is one, e.g. `home_%s`
355-
final String columnNamingPattern = findColumnNamingPattern( (ComponentPropertyHolder) parent.getPropertyHolder() );
356-
if ( columnNamingPattern != null ) {
357-
// apply the pattern - `home_city`
358-
realColumnName = String.format( columnNamingPattern, inferredColumnName );
359-
// we need to adjust the logical name to be picked up in `#addColumnBinding`
360-
logicalColumnName = realColumnName;
361-
}
354+
realColumnName = applyEmbeddedColumnNaming( realColumnName, (ComponentPropertyHolder) parent.getPropertyHolder() );
355+
// we need to adjust the logical name to be picked up in `#addColumnBinding`
356+
logicalColumnName = realColumnName;
362357
}
363358
mappingColumn.setName( realColumnName );
364359
}
365360
//Do nothing otherwise
366361
}
367362
}
368363

369-
private String findColumnNamingPattern(ComponentPropertyHolder propertyHolder) {
364+
private String applyEmbeddedColumnNaming(String inferredColumnName, ComponentPropertyHolder propertyHolder) {
365+
// code
366+
String result = inferredColumnName;
367+
370368
final String columnNamingPattern = propertyHolder.getComponent().getColumnNamingPattern();
371369
if ( StringHelper.isNotEmpty( columnNamingPattern ) ) {
372-
return columnNamingPattern;
370+
// zip_code
371+
result = String.format( columnNamingPattern, result );
373372
}
374373

375374
ComponentPropertyHolder tester = propertyHolder;
376375
while ( tester.parent.isComponent() ) {
377376
final ComponentPropertyHolder parentHolder = (ComponentPropertyHolder) tester.parent;
378377
final String parentColumnNamingPattern = parentHolder.getComponent().getColumnNamingPattern();
379378
if ( StringHelper.isNotEmpty( parentColumnNamingPattern ) ) {
380-
return parentColumnNamingPattern;
379+
// home_zip_code
380+
result = String.format( parentColumnNamingPattern, result );
381381
}
382382
tester = parentHolder;
383383
}
384384

385-
return null;
385+
return result;
386386
}
387387

388388
private String processColumnName(String columnName, boolean applyNamingStrategy) {

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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -998,13 +998,11 @@ static Component createEmbeddable(
998998
final ComponentPropertyHolder componentPropertyHolder = (ComponentPropertyHolder) propertyHolder;
999999
component.setParentAggregateColumn( componentPropertyHolder.getAggregateColumn() );
10001000
}
1001-
else {
1002-
applyColumnNamingPattern( component, propertyHolder, inferredData, context );
1003-
}
1001+
applyColumnNamingPattern( component, inferredData );
10041002
return component;
10051003
}
10061004

1007-
private static void applyColumnNamingPattern(Component component, PropertyHolder propertyHolder, PropertyData inferredData, MetadataBuildingContext context) {
1005+
private static void applyColumnNamingPattern(Component component, PropertyData inferredData) {
10081006
final Class<?> componentClass = component.getComponentClass();
10091007
if ( componentClass == null || Map.class.equals( componentClass ) ) {
10101008
// dynamic models

hibernate-core/src/test/java/org/hibernate/orm/test/naming/EmbeddedColumnNamingTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ void testBaselineNamingPattern(SessionFactoryScope sfScope) {
7171
verifyColumnNames( persister.findAttributeMapping( "homeAddress" ), "home_" );
7272
}
7373

74-
private void verifyColumnNames(AttributeMapping embeddedMapping, String prefix) {
74+
public static void verifyColumnNames(AttributeMapping embeddedMapping, String prefix) {
7575
embeddedMapping.forEachSelectable( (selectionIndex, selectableMapping) -> {
7676
assertThat( selectableMapping.getSelectionExpression() ).startsWith( prefix );
7777
} );
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*
2+
* SPDX-License-Identifier: LGPL-2.1-or-later
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.orm.test.naming;
6+
7+
import jakarta.persistence.Embeddable;
8+
import jakarta.persistence.Embedded;
9+
import jakarta.persistence.Entity;
10+
import jakarta.persistence.Id;
11+
import jakarta.persistence.Table;
12+
import org.hibernate.annotations.EmbeddedColumnNaming;
13+
import org.hibernate.engine.spi.SessionFactoryImplementor;
14+
import org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping;
15+
import org.hibernate.metamodel.spi.MappingMetamodelImplementor;
16+
import org.hibernate.persister.entity.EntityPersister;
17+
import org.hibernate.testing.orm.junit.DomainModel;
18+
import org.hibernate.testing.orm.junit.ServiceRegistry;
19+
import org.hibernate.testing.orm.junit.SessionFactory;
20+
import org.hibernate.testing.orm.junit.SessionFactoryScope;
21+
import org.junit.jupiter.api.Test;
22+
23+
import static org.hibernate.orm.test.naming.EmbeddedColumnNamingTests.verifyColumnNames;
24+
25+
/**
26+
* @author Steve Ebersole
27+
*/
28+
@SuppressWarnings("JUnitMalformedDeclaration")
29+
public class NestedEmbeddableNamingTests {
30+
31+
/**
32+
* Test use of {@code @EmbeddedColumnNaming} one 2 separate embedded attributes
33+
*/
34+
@Test
35+
@ServiceRegistry
36+
@DomainModel(annotatedClasses = {Address.class, Person.class})
37+
@SessionFactory
38+
void testNestedNamingPattern(SessionFactoryScope sfScope) {
39+
final SessionFactoryImplementor sessionFactory = sfScope.getSessionFactory();
40+
final MappingMetamodelImplementor mappingMetamodel = sessionFactory.getMappingMetamodel();
41+
final EntityPersister persister = mappingMetamodel.getEntityDescriptor( Person.class );
42+
43+
final EmbeddedAttributeMapping homeAddressMapping = (EmbeddedAttributeMapping) persister.findAttributeMapping( "homeAddress" );
44+
verifyColumnNames( homeAddressMapping, "home_" );
45+
final EmbeddedAttributeMapping homeZipMapping = (EmbeddedAttributeMapping) homeAddressMapping.getEmbeddableTypeDescriptor().findAttributeMapping( "zip" );
46+
verifyColumnNames( homeZipMapping, "home_zip" );
47+
48+
final EmbeddedAttributeMapping workAddressMapping = (EmbeddedAttributeMapping) persister.findAttributeMapping( "workAddress" );
49+
verifyColumnNames( workAddressMapping, "work_" );
50+
final EmbeddedAttributeMapping workZipMapping = (EmbeddedAttributeMapping) workAddressMapping.getEmbeddableTypeDescriptor().findAttributeMapping( "zip" );
51+
verifyColumnNames( workZipMapping, "work_zip" );
52+
}
53+
54+
@Entity(name="Person")
55+
@Table(name="person")
56+
public static class Person {
57+
@Id
58+
private Integer id;
59+
private String name;
60+
61+
@Embedded
62+
@EmbeddedColumnNaming("home_%s")
63+
private Address homeAddress;
64+
65+
@Embedded
66+
@EmbeddedColumnNaming("work_%s")
67+
private Address workAddress;
68+
}
69+
70+
@Embeddable
71+
public static class Address {
72+
private String street;
73+
private String city;
74+
private String state;
75+
@Embedded
76+
@EmbeddedColumnNaming( "zip_%s" )
77+
private ZipPlus zip;
78+
}
79+
80+
@Embeddable
81+
public static class ZipPlus {
82+
private String code;
83+
private String plus4;
84+
}
85+
}

0 commit comments

Comments
 (0)