Skip to content

Commit 236ba1d

Browse files
committed
HHH-6485 Add support for @DiscriminatorFormula
1 parent ac7feff commit 236ba1d

File tree

10 files changed

+173
-78
lines changed

10 files changed

+173
-78
lines changed

hibernate-core/src/main/java/org/hibernate/internal/util/collections/CollectionHelper.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,4 +127,20 @@ public static <K,V> ConcurrentHashMap<K,V> concurrentMap(int expectedNumberOfEle
127127
public static <T> List<T> arrayList(int anticipatedSize) {
128128
return new ArrayList<T>( anticipatedSize );
129129
}
130+
131+
public static boolean isEmpty(Collection collection) {
132+
return collection == null || collection.isEmpty();
133+
}
134+
135+
public static boolean isEmpty(Map map) {
136+
return map == null || map.isEmpty();
137+
}
138+
139+
public static boolean isNotEmpty(Collection collection) {
140+
return !isEmpty( collection );
141+
}
142+
143+
public static boolean isNotEmpty(Map map) {
144+
return !isEmpty( map );
145+
}
130146
}

hibernate-core/src/main/java/org/hibernate/metamodel/binding/EntityBinding.java

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ public class EntityBinding implements AttributeBindingContainer {
5454

5555
private Entity entity;
5656
private TableSpecification primaryTable;
57+
private String primaryTableName;
5758
private Map<String, TableSpecification> secondaryTables = new HashMap<String, TableSpecification>();
5859

5960
private Value<Class<?>> proxyInterfaceType;
@@ -142,17 +143,29 @@ public void setPrimaryTable(TableSpecification primaryTable) {
142143
this.primaryTable = primaryTable;
143144
}
144145

145-
public TableSpecification locateTable(String tableName) {
146-
if ( tableName == null ) {
147-
return primaryTable;
148-
}
149-
150-
TableSpecification tableSpec = secondaryTables.get( tableName );
151-
if ( tableSpec == null ) {
152-
throw new AssertionFailure( String.format("Unable to find table %s amongst tables %s", tableName, secondaryTables.keySet()) );
153-
}
154-
return tableSpec;
155-
}
146+
public TableSpecification locateTable(String tableName) {
147+
if ( tableName == null || tableName.equals( getPrimaryTableName() ) ) {
148+
return primaryTable;
149+
}
150+
TableSpecification tableSpec = secondaryTables.get( tableName );
151+
if ( tableSpec == null ) {
152+
throw new AssertionFailure(
153+
String.format(
154+
"Unable to find table %s amongst tables %s",
155+
tableName,
156+
secondaryTables.keySet()
157+
)
158+
);
159+
}
160+
return tableSpec;
161+
}
162+
public String getPrimaryTableName() {
163+
return primaryTableName;
164+
}
165+
166+
public void setPrimaryTableName(String primaryTableName) {
167+
this.primaryTableName = primaryTableName;
168+
}
156169

157170
public void addSecondaryTable(String tableName, TableSpecification table) {
158171
secondaryTables.put( tableName, table );

hibernate-core/src/main/java/org/hibernate/metamodel/relational/Column.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
* @author Gavin King
3535
* @author Steve Ebersole
3636
*/
37-
public class Column extends AbstractSimpleValue implements SimpleValue {
37+
public class Column extends AbstractSimpleValue {
3838
private final Identifier columnName;
3939
private boolean nullable;
4040
private boolean unique;

hibernate-core/src/main/java/org/hibernate/metamodel/relational/DerivedValue.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
*
3131
* @author Steve Ebersole
3232
*/
33-
public class DerivedValue extends AbstractSimpleValue implements SimpleValue {
33+
public class DerivedValue extends AbstractSimpleValue {
3434
private final String expression;
3535

3636
public DerivedValue(TableSpecification table, int position, String expression) {

hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/AnnotationMetadataSourceProcessorImpl.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535

3636
import org.hibernate.AssertionFailure;
3737
import org.hibernate.HibernateException;
38+
import org.hibernate.internal.util.collections.CollectionHelper;
3839
import org.hibernate.metamodel.MetadataSources;
3940
import org.hibernate.metamodel.source.MetadataImplementor;
4041
import org.hibernate.metamodel.source.MetadataSourceProcessor;
@@ -97,7 +98,7 @@ public void prepare(MetadataSources sources) {
9798
index = parseAndUpdateIndex( mappings, index );
9899
}
99100

100-
if ( index.getAnnotations( PseudoJpaDotNames.DEFAULT_DELIMITED_IDENTIFIERS ) != null ) {
101+
if ( CollectionHelper.isNotEmpty( index.getAnnotations( PseudoJpaDotNames.DEFAULT_DELIMITED_IDENTIFIERS ) ) ) {
101102
// todo : this needs to move to AnnotationBindingContext
102103
// what happens right now is that specifying this in an orm.xml causes it to effect all orm.xmls
103104
metadata.setGloballyQuotedIdentifiers( true );

hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/attribute/DiscriminatorSourceImpl.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,12 @@ public boolean isInserted() {
4747
return entityClass.isDiscriminatorIncludedInSql();
4848
}
4949

50-
@Override
51-
public RelationalValueSource getDiscriminatorRelationalValueSource() {
52-
return new ColumnValuesSourceImpl( entityClass.getDiscriminatorColumnValues() );
53-
}
50+
@Override
51+
public RelationalValueSource getDiscriminatorRelationalValueSource() {
52+
return entityClass.getDiscriminatorFormula() != null ? entityClass.getDiscriminatorFormula() : new ColumnValuesSourceImpl(
53+
entityClass.getDiscriminatorColumnValues()
54+
);
55+
}
5456

5557
@Override
5658
public String getExplicitHibernateTypeName() {

hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntityClass.java

Lines changed: 50 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
import org.hibernate.metamodel.source.annotations.JandexHelper;
5757
import org.hibernate.metamodel.source.annotations.attribute.ColumnValues;
5858
import org.hibernate.metamodel.source.binder.ConstraintSource;
59+
import org.hibernate.metamodel.source.binder.DerivedValueSource;
5960
import org.hibernate.metamodel.source.binder.TableSource;
6061

6162
/**
@@ -96,6 +97,7 @@ public class EntityClass extends ConfiguredClass {
9697
private String proxy;
9798

9899
private ColumnValues discriminatorColumnValues;
100+
private DerivedValueSource discriminatorFormula;
99101
private Class<?> discriminatorType;
100102
private String discriminatorMatchValue;
101103
private boolean isDiscriminatorForced = true;
@@ -144,6 +146,10 @@ public ColumnValues getDiscriminatorColumnValues() {
144146
return discriminatorColumnValues;
145147
}
146148

149+
public DerivedValueSource getDiscriminatorFormula() {
150+
return discriminatorFormula;
151+
}
152+
147153
public Class<?> getDiscriminatorType() {
148154
return discriminatorType;
149155
}
@@ -339,10 +345,22 @@ private void processDiscriminator() {
339345
final AnnotationInstance discriminatorColumnAnnotation = JandexHelper.getSingleAnnotation(
340346
getClassInfo(), JPADotNames.DISCRIMINATOR_COLUMN
341347
);
342-
discriminatorColumnValues = new ColumnValues( discriminatorColumnAnnotation );
343-
discriminatorColumnValues.setNullable( false ); // discriminator column cannot be null
348+
349+
final AnnotationInstance discriminatorFormulaAnnotation = JandexHelper.getSingleAnnotation(
350+
getClassInfo(),
351+
HibernateDotNames.DISCRIMINATOR_FORMULA
352+
);
353+
354+
344355
Class<?> type = String.class; // string is the discriminator default
356+
if ( discriminatorFormulaAnnotation != null ) {
357+
String expression = JandexHelper.getValue( discriminatorFormulaAnnotation, "value", String.class );
358+
discriminatorFormula = new FormulaImpl( getPrimaryTableSource().getExplicitTableName(), expression );
359+
}
360+
discriminatorColumnValues = new ColumnValues( null ); //(stliu) give null here, will populate values below
361+
discriminatorColumnValues.setNullable( false ); // discriminator column cannot be null
345362
if ( discriminatorColumnAnnotation != null ) {
363+
346364
DiscriminatorType discriminatorType = Enum.valueOf(
347365
DiscriminatorType.class, discriminatorColumnAnnotation.value( "discriminatorType" ).asEnum()
348366
);
@@ -378,12 +396,13 @@ private void processDiscriminator() {
378396
Integer.class
379397
)
380398
);
381-
if ( discriminatorColumnAnnotation.value( "columnDefinition" ) != null ) {
382-
discriminatorColumnValues.setColumnDefinition(
383-
discriminatorColumnAnnotation.value( "columnDefinition" )
384-
.asString()
399+
discriminatorColumnValues.setColumnDefinition(
400+
JandexHelper.getValue(
401+
discriminatorColumnAnnotation,
402+
"columnDefinition",
403+
String.class
404+
)
385405
);
386-
}
387406
}
388407
discriminatorType = type;
389408

@@ -547,83 +566,60 @@ private Caching determineCachingSettings() {
547566
}
548567

549568
/**
569+
* todo see {@code Binder#createTable}
550570
* @param tableAnnotation a annotation instance, either {@link javax.persistence.Table} or {@link javax.persistence.SecondaryTable}
551571
*
552572
* @return A table source for the specified annotation instance
553573
*/
554574
private TableSource createTableSource(AnnotationInstance tableAnnotation) {
555-
String schema = getLocalBindingContext().getMappingDefaults().getSchemaName();
556-
String catalog = getLocalBindingContext().getMappingDefaults().getCatalogName();
557-
558-
575+
String schema = null;
576+
String catalog = null;
559577
if ( tableAnnotation != null ) {
560-
final AnnotationValue schemaValue = tableAnnotation.value( "schema" );
561-
if ( schemaValue != null ) {
562-
schema = schemaValue.asString();
563-
}
564-
565-
final AnnotationValue catalogValue = tableAnnotation.value( "catalog" );
566-
if ( catalogValue != null ) {
567-
catalog = catalogValue.asString();
568-
}
569-
}
570-
571-
if ( getLocalBindingContext().isGloballyQuotedIdentifiers() ) {
572-
schema = StringHelper.quote( schema );
573-
catalog = StringHelper.quote( catalog );
578+
schema = JandexHelper.getValue( tableAnnotation, "schema", String.class );
579+
catalog = JandexHelper.getValue( tableAnnotation, "catalog", String.class );
574580
}
575-
576581
// process the table name
577582
String tableName = null;
578-
String explicitTableName = null;
583+
String logicalTableName = null;
579584

580585
if ( tableAnnotation != null ) {
581-
explicitTableName = JandexHelper.getValue( tableAnnotation, "name", String.class );
582-
if ( StringHelper.isNotEmpty( explicitTableName ) ) {
583-
tableName = getLocalBindingContext().getNamingStrategy().tableName( explicitTableName );
584-
if ( getLocalBindingContext().isGloballyQuotedIdentifiers() && !Identifier.isQuoted( explicitTableName ) ) {
585-
tableName = StringHelper.quote( tableName );
586-
}
586+
logicalTableName = JandexHelper.getValue( tableAnnotation, "name", String.class );
587+
if ( StringHelper.isNotEmpty( logicalTableName ) ) {
588+
tableName = logicalTableName;
587589
}
588590
createUniqueConstraints( tableAnnotation, tableName );
589591
}
590592

591-
592-
// use the simple table name as default in case there was no table annotation
593-
if ( tableName == null ) {
594-
if ( explicitEntityName == null ) {
595-
tableName = getConfiguredClass().getSimpleName();
596-
}
597-
else {
598-
tableName = explicitEntityName;
599-
}
600-
}
601-
602593
TableSourceImpl tableSourceImpl;
603594
if ( tableAnnotation == null || JPADotNames.TABLE.equals( tableAnnotation.name() ) ) {
604595
// for the main table @Table we use 'null' as logical name
605596
tableSourceImpl = new TableSourceImpl( schema, catalog, tableName, null );
606597
}
607598
else {
608599
// for secondary tables a name must be specified which is used as logical table name
609-
tableSourceImpl = new TableSourceImpl( schema, catalog, tableName, explicitTableName );
600+
tableSourceImpl = new TableSourceImpl( schema, catalog, tableName, logicalTableName );
610601
}
611602
return tableSourceImpl;
612603
}
613604

614-
private Set<TableSource> createSecondaryTableSources() {
605+
private Set<TableSource> createSecondaryTableSources() {
615606
Set<TableSource> secondaryTableSources = new HashSet<TableSource>();
616-
607+
AnnotationInstance secondaryTables = JandexHelper.getSingleAnnotation(
608+
getClassInfo(),
609+
JPADotNames.SECONDARY_TABLES
610+
);
611+
AnnotationInstance secondaryTable = JandexHelper.getSingleAnnotation(
612+
getClassInfo(),
613+
JPADotNames.SECONDARY_TABLE
614+
);
617615
// collect all @secondaryTable annotations
618616
List<AnnotationInstance> secondaryTableAnnotations = new ArrayList<AnnotationInstance>();
619-
secondaryTableAnnotations.add(
620-
JandexHelper.getSingleAnnotation( getClassInfo(), JPADotNames.SECONDARY_TABLE )
621-
);
617+
if ( secondaryTable != null ) {
618+
secondaryTableAnnotations.add(
619+
secondaryTable
620+
);
621+
}
622622

623-
AnnotationInstance secondaryTables = JandexHelper.getSingleAnnotation(
624-
getClassInfo(),
625-
JPADotNames.SECONDARY_TABLES
626-
);
627623
if ( secondaryTables != null ) {
628624
secondaryTableAnnotations.addAll(
629625
Arrays.asList(
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package org.hibernate.metamodel.source.annotations.entity;
2+
3+
import org.hibernate.metamodel.source.binder.DerivedValueSource;
4+
5+
/**
6+
* @author Strong Liu
7+
*/
8+
public class FormulaImpl implements DerivedValueSource{
9+
private String tableName;
10+
private final String expression;
11+
12+
FormulaImpl(String tableName, String expression) {
13+
this.tableName = tableName;
14+
this.expression = expression;
15+
}
16+
17+
@Override
18+
public String getExpression() {
19+
return expression;
20+
}
21+
22+
@Override
23+
public String getContainingTableName() {
24+
return tableName;
25+
}
26+
}

hibernate-core/src/main/java/org/hibernate/metamodel/source/binder/Binder.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ private EntityBinding makeDiscriminatedSubclassBinding(SubclassEntitySource enti
269269
final EntityBinding entityBinding = buildBasicEntityBinding( entitySource, superEntityBinding );
270270

271271
entityBinding.setPrimaryTable( superEntityBinding.getPrimaryTable() );
272-
272+
entityBinding.setPrimaryTableName( superEntityBinding.getPrimaryTableName() );
273273
bindDiscriminatorValue( entitySource, entityBinding );
274274

275275
return entityBinding;
@@ -439,7 +439,9 @@ private void bindComponent(ComponentAttributeSource attributeSource, AttributeBi
439439
}
440440

441441
private void bindPersistentCollection(PluralAttributeSource attributeSource, AttributeBindingContainer attributeBindingContainer) {
442-
final PluralAttribute existingAttribute = attributeBindingContainer.getAttributeContainer().locatePluralAttribute( attributeSource.getName() );
442+
final PluralAttribute existingAttribute = attributeBindingContainer.getAttributeContainer().locatePluralAttribute(
443+
attributeSource.getName()
444+
);
443445
final AbstractPluralAttributeBinding pluralAttributeBinding;
444446

445447
if ( attributeSource.getPluralAttributeNature() == PluralAttributeNature.BAG ) {
@@ -471,7 +473,9 @@ private CollectionElementNature convert(PluralAttributeElementNature pluralAttri
471473
private BasicAttributeBinding doBasicSingularAttributeBindingCreation(
472474
SingularAttributeSource attributeSource,
473475
AttributeBindingContainer attributeBindingContainer) {
474-
final SingularAttribute existingAttribute = attributeBindingContainer.getAttributeContainer().locateSingularAttribute( attributeSource.getName() );
476+
final SingularAttribute existingAttribute = attributeBindingContainer.getAttributeContainer().locateSingularAttribute(
477+
attributeSource.getName()
478+
);
475479
final SingularAttribute attribute;
476480
if ( existingAttribute != null ) {
477481
attribute = existingAttribute;
@@ -641,6 +645,7 @@ private void bindPrimaryTable(EntitySource entitySource, EntityBinding entityBin
641645
final TableSource tableSource = entitySource.getPrimaryTable();
642646
final Table table = createTable( entityBinding, tableSource );
643647
entityBinding.setPrimaryTable( table );
648+
entityBinding.setPrimaryTableName( table.getTableName().getName() );
644649
}
645650

646651
private void bindSecondaryTables(EntitySource entitySource, EntityBinding entityBinding) {
@@ -653,12 +658,12 @@ private void bindSecondaryTables(EntitySource entitySource, EntityBinding entity
653658
private Table createTable(EntityBinding entityBinding, TableSource tableSource) {
654659
final String schemaName = StringHelper.isEmpty( tableSource.getExplicitSchemaName() )
655660
? currentBindingContext.getMappingDefaults().getSchemaName()
656-
: currentBindingContext.getMetadataImplementor().getOptions().isGloballyQuotedIdentifiers()
661+
: currentBindingContext.isGloballyQuotedIdentifiers()
657662
? StringHelper.quote( tableSource.getExplicitSchemaName() )
658663
: tableSource.getExplicitSchemaName();
659664
final String catalogName = StringHelper.isEmpty( tableSource.getExplicitCatalogName() )
660665
? currentBindingContext.getMappingDefaults().getCatalogName()
661-
: currentBindingContext.getMetadataImplementor().getOptions().isGloballyQuotedIdentifiers()
666+
: currentBindingContext.isGloballyQuotedIdentifiers()
662667
? StringHelper.quote( tableSource.getExplicitCatalogName() )
663668
: tableSource.getExplicitCatalogName();
664669

0 commit comments

Comments
 (0)