Hibernate 5 ImplicitNamingStrategy

I want to use hibernate 5.x. With hibernate 5.x, there are new interfaces for ImplicitNamingStrategy and PhysicalNamingStrategy .

For the name property of the User object, I want to have the column name user_name in my database. I do not want to comment on all properties with @Column(name="...") . I tried writing custom ImplicitNamingStrategy , but there is no way to get the name of the owner of the object.

 public class MyNamingStrategy extends ImplicitNamingStrategyComponentPathImpl { @Override public Identifier determineBasicColumnName ( ImplicitBasicColumnNameSource source ) { // How to get the name of the owning entity? String owningEntityName = "howdoigetthis"; Identifier basicColumnName = super.determineBasicColumnName(source); Identifier identifier = Identifier.toIdentifier(owningEntityName +"_" + basicColumnName.toString()); return identifier; } } 

Is there a way to prefix each column with a table (or entity) name just by using NamingStrategy?

+3
hibernate
source share
3 answers

Here is the solution if you don't mind a bit of dirty reflection:

 @Override public Identifier determineBasicColumnName(final ImplicitBasicColumnNameSource source) { // Get 'this$0' field and make it accessible Field ejb3ColumnField = null; final Field[] sourceFields = source.getClass().getDeclaredFields(); for (final Field sourceField : sourceFields) { if (sourceField.getName().equals("this$0")) { ejb3ColumnField = sourceField; } } ejb3ColumnField.setAccessible(true); // Get actual field object String owningEntityName; Ejb3Column ejb3Column; try { ejb3Column = (Ejb3Column) ejb3ColumnField.get(source); } catch ( IllegalArgumentException | IllegalAccessException e) { throw new RuntimeException(e); // (Or deal with this appropriately, eg log it.) } // The property holder path holds the owning entity fully qualified name final String owningEntityFullyQualifiedName = ejb3Column.getPropertyHolder().getPath(); // The entity name is after the last dot in the fully qualified name final String[] owningEntityTokens = owningEntityFullyQualifiedName.split("\\."); owningEntityName = owningEntityTokens[owningEntityTokens.length - 1]; final Identifier basicColumnName = super.determineBasicColumnName(source); return Identifier.toIdentifier(owningEntityName + "_" + basicColumnName.toString()); } 
+3
source share

This is my final decision based on Steve Chambers answer. These solutions even take into account the explicit designation of annotations and correct the join column name. But Steve should get all the credit for his answer

 public class JlotImplicitNamingStrategy extends ImplicitNamingStrategyComponentPathImpl { @Override public Identifier determineJoinColumnName ( ImplicitJoinColumnNameSource source ) { String name = source.getReferencedColumnName().toString(); Identifier identifier = toIdentifier(name, source.getBuildingContext()); return identifier; } @Override public Identifier determineBasicColumnName ( ImplicitBasicColumnNameSource source ) { try { Field ejb3ColumnField = source.getClass().getDeclaredField("this$0"); ejb3ColumnField.setAccessible(true); Ejb3Column ejb3Column = (Ejb3Column) ejb3ColumnField.get(source); // explicit naming oder implicit String tableName = ejb3Column.getPropertyHolder().getTable().getName(); final Identifier basicColumnName = super.determineBasicColumnName(source); String columnName = tableName + "_" + basicColumnName.toString(); return Identifier.toIdentifier(columnName); } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) { throw new RuntimeException(e); } } } 
+3
source share

I implemented both interfaces that give 99.99% result as sleep mode 4:

 public class ImprovedNamingStrategy implements PhysicalNamingStrategy { @Override public Identifier toPhysicalCatalogName(Identifier identifier, JdbcEnvironment jdbcEnv) { return convert(identifier); } @Override public Identifier toPhysicalColumnName(Identifier identifier, JdbcEnvironment jdbcEnv) { return convert(identifier); } @Override public Identifier toPhysicalSchemaName(Identifier identifier, JdbcEnvironment jdbcEnv) { return convert(identifier); } @Override public Identifier toPhysicalSequenceName(Identifier identifier, JdbcEnvironment jdbcEnv) { return convert(identifier); } @Override public Identifier toPhysicalTableName(Identifier identifier, JdbcEnvironment jdbcEnv) { return convert(identifier); } /** * Converts table name. * * @param identifier the identifier. * @return the identifier. */ private Identifier convert(Identifier identifier) { if (identifier == null || StringUtils.isBlank(identifier.getText())) { return identifier; } final StringBuilder buf = new StringBuilder(identifier.getText().replace('.', '_')); for (int i = 1; i < buf.length() - 1; i++) { if ( Character.isLowerCase(buf.charAt(i - 1)) && Character.isUpperCase(buf.charAt(i)) && Character.isLowerCase(buf.charAt(i + 1)) ) { buf.insert(i++, '_'); } } String newName = Strings.toLowerCase(buf.toString()); return Identifier.toIdentifier(newName); } } 

and

 public class ImprovedImplicitNamingStrategy implements ImplicitNamingStrategy { /** * The INSTANCE. */ public static final ImprovedImplicitNamingStrategy INSTANCE = new ImprovedImplicitNamingStrategy(); /** * Constructor. */ public ImprovedImplicitNamingStrategy() { } /** * The determinePrimaryTableName. * * @param source the source. * @return the identifier. */ @Override public Identifier determinePrimaryTableName(ImplicitEntityNameSource source) { if (source == null) { // should never happen, but to be defensive... throw new HibernateException("Entity naming information was not provided."); } String tableName = transformEntityName(source.getEntityNaming()); if (tableName == null) { // todo : add info to error message - but how to know what to write since we failed to interpret the naming source throw new HibernateException("Could not determine primary table name for entity"); } return toIdentifier(tableName, source.getBuildingContext()); } /** * The determinePrimaryTableName. * * @param entityNaming the source. * @return the identifier. */ protected String transformEntityName(EntityNaming entityNaming) { // prefer the JPA entity name, if specified... if (StringHelper.isNotEmpty(entityNaming.getJpaEntityName())) { return entityNaming.getJpaEntityName(); } else { // otherwise, use the Hibernate entity name return StringHelper.unqualify(entityNaming.getEntityName()); } } /** * The determinePrimaryTableName. * * @param source the source. * @return the identifier. */ @Override public Identifier determineJoinTableName(ImplicitJoinTableNameSource source) { final String ownerPortion = source.getOwningPhysicalTableName(); final String ownedPortion; if (source.getAssociationOwningAttributePath() != null) { ownedPortion = transformAttributePath(source.getAssociationOwningAttributePath()); } else { ownedPortion = source.getNonOwningPhysicalTableName(); } return toIdentifier(ownerPortion + "_" + ownedPortion, source.getBuildingContext()); } /** * The determinePrimaryTableName. * * @param source the source. * @return the identifier. */ @Override public Identifier determineCollectionTableName(ImplicitCollectionTableNameSource source) { final String owningEntity = transformEntityName(source.getOwningEntityNaming()); final String name = transformAttributePath(source.getOwningAttributePath()); final String entityName; if (!Strings.isNullOrEmpty(owningEntity)) { entityName = owningEntity + "_" + name; } else { entityName = name; } return toIdentifier(entityName, source.getBuildingContext()); } /** * The determinePrimaryTableName. * * @param source the source. * @return the identifier. */ @Override public Identifier determineIdentifierColumnName(ImplicitIdentifierColumnNameSource source) { return toIdentifier(transformAttributePath(source.getIdentifierAttributePath()), source.getBuildingContext()); } /** * The determinePrimaryTableName. * * @param source the source. * @return the identifier. */ @Override public Identifier determineDiscriminatorColumnName(ImplicitDiscriminatorColumnNameSource source) { return toIdentifier( source.getBuildingContext().getMappingDefaults().getImplicitDiscriminatorColumnName(), source.getBuildingContext()); } /** * The determinePrimaryTableName. * * @param source the source. * @return the identifier. */ @Override public Identifier determineTenantIdColumnName(ImplicitTenantIdColumnNameSource source) { return toIdentifier(source.getBuildingContext().getMappingDefaults().getImplicitTenantIdColumnName(), source.getBuildingContext()); } /** * The determinePrimaryTableName. * * @param source the source. * @return the identifier. */ @Override public Identifier determineBasicColumnName(ImplicitBasicColumnNameSource source) { return toIdentifier(transformAttributePath(source.getAttributePath()), source.getBuildingContext()); } /** * The determineJoinColumnName. * * @param source the source. * @return identifier. */ @Override public Identifier determineJoinColumnName(ImplicitJoinColumnNameSource source) { final String name; if (source.getNature() == ImplicitJoinColumnNameSource.Nature.ELEMENT_COLLECTION) { name = transformEntityName(source.getEntityNaming()) + '_' + source.getReferencedColumnName().getText(); } else { if (source.getAttributePath() == null) { name = source.getReferencedTableName().getText(); } else { name = transformAttributePath(source.getAttributePath()); } } return toIdentifier(name, source.getBuildingContext()); } /** * The determinePrimaryTableName. * * @param source the source. * @return the identifier. */ @Override public Identifier determinePrimaryKeyJoinColumnName(ImplicitPrimaryKeyJoinColumnNameSource source) { return source.getReferencedPrimaryKeyColumnName(); } /** * The determinePrimaryTableName. * * @param source the source. * @return the identifier. */ @Override public Identifier determineAnyDiscriminatorColumnName(ImplicitAnyDiscriminatorColumnNameSource source) { return toIdentifier( transformAttributePath(source.getAttributePath()) + "_" + source.getBuildingContext().getMappingDefaults().getImplicitDiscriminatorColumnName(), source.getBuildingContext()); } /** * The determinePrimaryTableName. * * @param source the source. * @return the identifier. */ @Override public Identifier determineAnyKeyColumnName(ImplicitAnyKeyColumnNameSource source) { return toIdentifier( transformAttributePath(source.getAttributePath()) + "_" + source.getBuildingContext().getMappingDefaults().getImplicitIdColumnName(), source.getBuildingContext()); } /** * The determinePrimaryTableName. * * @param source the source. * @return the identifier. */ @Override public Identifier determineMapKeyColumnName(ImplicitMapKeyColumnNameSource source) { return toIdentifier( transformAttributePath(source.getPluralAttributePath()) + "_KEY", source.getBuildingContext() ); } /** * The determinePrimaryTableName. * * @param source the source. * @return the identifier. */ @Override public Identifier determineListIndexColumnName(ImplicitIndexColumnNameSource source) { return toIdentifier(transformAttributePath(source.getPluralAttributePath()) + "_ORDER", source.getBuildingContext()); } /** * The determinePrimaryTableName. * * @param source the source. * @return the identifier. */ @Override public Identifier determineForeignKeyName(ImplicitForeignKeyNameSource source) { return toIdentifier( NamingHelper.INSTANCE.generateHashedFkName( "FK", source.getTableName(), source.getReferencedTableName(), source.getColumnNames() ), source.getBuildingContext() ); } /** * The determinePrimaryTableName. * * @param source the source. * @return the identifier. */ @Override public Identifier determineUniqueKeyName(ImplicitUniqueKeyNameSource source) { return toIdentifier( NamingHelper.INSTANCE.generateHashedConstraintName( "UK", source.getTableName(), source.getColumnNames() ), source.getBuildingContext() ); } /** * The determinePrimaryTableName. * * @param source the source. * @return the identifier. */ @Override public Identifier determineIndexName(ImplicitIndexNameSource source) { return toIdentifier( NamingHelper.INSTANCE.generateHashedConstraintName( "IDX", source.getTableName(), source.getColumnNames() ), source.getBuildingContext() ); } /** * For JPA standards we typically need the unqualified name. However, a more usable * impl tends to use the whole path. This method provides an easy hook for subclasses * to accomplish that * * @param attributePath The attribute path * @return The extracted name */ protected String transformAttributePath(AttributePath attributePath) { return attributePath.getProperty(); } /** * Easy hook to build an Identifier using the keyword safe IdentifierHelper. * * @param stringForm The String form of the name * @param buildingContext Access to the IdentifierHelper * @return The identifier */ protected Identifier toIdentifier(String stringForm, MetadataBuildingContext buildingContext) { return buildingContext.getMetadataCollector() .getDatabase() .getJdbcEnvironment() .getIdentifierHelper() .toIdentifier(stringForm); } } 

N'joy.

+2
source share

All Articles