private String buildDefaultColumnName( final PersistentClass referencedEntity, final String logicalReferencedColumn) { final Database database = getBuildingContext().getMetadataCollector().getDatabase(); final ImplicitNamingStrategy implicitNamingStrategy = getBuildingContext().getBuildingOptions().getImplicitNamingStrategy(); final PhysicalNamingStrategy physicalNamingStrategy = getBuildingContext().getBuildingOptions().getPhysicalNamingStrategy(); Identifier columnIdentifier; boolean mappedBySide = mappedByTableName != null || mappedByPropertyName != null; boolean ownerSide = getPropertyName() != null; Boolean isRefColumnQuoted = StringHelper.isQuoted(logicalReferencedColumn); final String unquotedLogicalReferenceColumn = isRefColumnQuoted ? StringHelper.unquote(logicalReferencedColumn) : logicalReferencedColumn; if (mappedBySide) { // NOTE : While it is completely misleading here to allow for the combination // of a "JPA ElementCollection" to be mappedBy, the code that uses this // class relies on this behavior for handling the inverse side of // many-to-many mappings final AttributePath attributePath = AttributePath.parse(mappedByPropertyName); final ImplicitJoinColumnNameSource.Nature implicitNamingNature; if (getPropertyHolder().isEntity()) { implicitNamingNature = ImplicitJoinColumnNameSource.Nature.ENTITY; } else if (JPA2ElementCollection) { implicitNamingNature = ImplicitJoinColumnNameSource.Nature.ELEMENT_COLLECTION; } else { implicitNamingNature = ImplicitJoinColumnNameSource.Nature.ENTITY_COLLECTION; } columnIdentifier = implicitNamingStrategy.determineJoinColumnName( new ImplicitJoinColumnNameSource() { private final EntityNaming entityNaming = new EntityNaming() { @Override public String getClassName() { return referencedEntity.getClassName(); } @Override public String getEntityName() { return referencedEntity.getEntityName(); } @Override public String getJpaEntityName() { return referencedEntity.getJpaEntityName(); } }; private final Identifier referencedTableName = getBuildingContext() .getMetadataCollector() .getDatabase() .toIdentifier(mappedByTableName); @Override public Nature getNature() { return implicitNamingNature; } @Override public EntityNaming getEntityNaming() { return entityNaming; } @Override public AttributePath getAttributePath() { return attributePath; } @Override public Identifier getReferencedTableName() { return referencedTableName; } @Override public Identifier getReferencedColumnName() { if (logicalReferencedColumn != null) { return getBuildingContext() .getMetadataCollector() .getDatabase() .toIdentifier(logicalReferencedColumn); } if (mappedByEntityName == null || mappedByPropertyName == null) { return null; } final PersistentClass mappedByEntityBinding = getBuildingContext() .getMetadataCollector() .getEntityBinding(mappedByEntityName); final Property mappedByProperty = mappedByEntityBinding.getProperty(mappedByPropertyName); final SimpleValue value = (SimpleValue) mappedByProperty.getValue(); final Iterator<Selectable> selectableValues = value.getColumnIterator(); if (!selectableValues.hasNext()) { throw new AnnotationException( String.format( Locale.ENGLISH, "mapped-by [%s] defined for attribute [%s] referenced an invalid property (no columns)", mappedByPropertyName, propertyHolder.getPath())); } final Selectable selectable = selectableValues.next(); if (!Column.class.isInstance(selectable)) { throw new AnnotationException( String.format( Locale.ENGLISH, "mapped-by [%s] defined for attribute [%s] referenced an invalid property (formula)", mappedByPropertyName, propertyHolder.getPath())); } if (selectableValues.hasNext()) { throw new AnnotationException( String.format( Locale.ENGLISH, "mapped-by [%s] defined for attribute [%s] referenced an invalid property (multiple columns)", mappedByPropertyName, propertyHolder.getPath())); } return getBuildingContext() .getMetadataCollector() .getDatabase() .toIdentifier(((Column) selectable).getQuotedName()); } @Override public MetadataBuildingContext getBuildingContext() { return Ejb3JoinColumn.this.getBuildingContext(); } }); // one element was quoted so we quote if (isRefColumnQuoted || StringHelper.isQuoted(mappedByTableName)) { columnIdentifier = Identifier.quote(columnIdentifier); } } else if (ownerSide) { final String logicalTableName = getBuildingContext() .getMetadataCollector() .getLogicalTableName(referencedEntity.getTable()); final ImplicitJoinColumnNameSource.Nature implicitNamingNature; if (JPA2ElementCollection) { implicitNamingNature = ImplicitJoinColumnNameSource.Nature.ELEMENT_COLLECTION; } else if (getPropertyHolder().isEntity()) { implicitNamingNature = ImplicitJoinColumnNameSource.Nature.ENTITY; } else { implicitNamingNature = ImplicitJoinColumnNameSource.Nature.ENTITY_COLLECTION; } columnIdentifier = getBuildingContext() .getBuildingOptions() .getImplicitNamingStrategy() .determineJoinColumnName( new ImplicitJoinColumnNameSource() { private final EntityNaming entityNaming = new EntityNaming() { @Override public String getClassName() { return referencedEntity.getClassName(); } @Override public String getEntityName() { return referencedEntity.getEntityName(); } @Override public String getJpaEntityName() { return referencedEntity.getJpaEntityName(); } }; private final AttributePath attributePath = AttributePath.parse(getPropertyName()); private final Identifier referencedTableName = getBuildingContext() .getMetadataCollector() .getDatabase() .toIdentifier(logicalTableName); private final Identifier referencedColumnName = getBuildingContext() .getMetadataCollector() .getDatabase() .toIdentifier(logicalReferencedColumn); @Override public Nature getNature() { return implicitNamingNature; } @Override public EntityNaming getEntityNaming() { return entityNaming; } @Override public AttributePath getAttributePath() { return attributePath; } @Override public Identifier getReferencedTableName() { return referencedTableName; } @Override public Identifier getReferencedColumnName() { return referencedColumnName; } @Override public MetadataBuildingContext getBuildingContext() { return Ejb3JoinColumn.this.getBuildingContext(); } }); // one element was quoted so we quote if (isRefColumnQuoted || StringHelper.isQuoted(logicalTableName)) { columnIdentifier = Identifier.quote(columnIdentifier); } } else { final Identifier logicalTableName = database.toIdentifier( getBuildingContext() .getMetadataCollector() .getLogicalTableName(referencedEntity.getTable())); // is an intra-entity hierarchy table join so copy the name by default columnIdentifier = implicitNamingStrategy.determinePrimaryKeyJoinColumnName( new ImplicitPrimaryKeyJoinColumnNameSource() { @Override public MetadataBuildingContext getBuildingContext() { return Ejb3JoinColumn.this.getBuildingContext(); } @Override public Identifier getReferencedTableName() { return logicalTableName; } @Override public Identifier getReferencedPrimaryKeyColumnName() { return database.toIdentifier(logicalReferencedColumn); } }); if (!columnIdentifier.isQuoted() && (isRefColumnQuoted || logicalTableName.isQuoted())) { columnIdentifier = Identifier.quote(columnIdentifier); } } return physicalNamingStrategy .toPhysicalColumnName(columnIdentifier, database.getJdbcEnvironment()) .render(database.getJdbcEnvironment().getDialect()); }