Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate 5 ImplicitNamingStrategy

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

For a property name of an entity User I want to have a column name user_name in my database. I do not want to annotate every property with @Column(name="..."). I tried to write a custom ImplicitNamingStrategy but there is no way to get the name of the owning entity.

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 every column with the table (or entity) name by just using a NamingStrategy?

like image 981
Janning Avatar asked Oct 13 '15 20:10

Janning


People also ask

What is PhysicalNamingStrategy?

The Hibernate PhysicalNamingStrategy methods allow you to customize the default naming conventions for the following database identifiers: toPhysicalCatalogName – customize the default database catalog naming convention. toPhysicalSchemaName – customize the default database schema naming convention.

What is naming strategy in hibernate?

Implicit Naming StrategyHibernate uses a logical name to map an entity or attribute name to a table or column name. This name can be customized in two ways: it can be derived automatically by using an ImplicitNamingStrategy or it can be defined explicitly by using annotations.

What is Spring JPA Hibernate naming strategy?

naming. strategy ; Hibernate 5 defines a Physical and Implicit naming strategies. Spring Boot configures SpringPhysicalNamingStrategy by default. This implementation provides the same table structure as Hibernate 4: all dots are replaced by underscores and camel cases are replaced by underscores as well.

What is ImprovedNamingStrategy?

ImprovedNamingStrategy , which will convert the mixed case names to the embedded underscores name .


2 Answers

This is my final solution based on Steve Chambers answer. This solutions even takes into account an explicit naming with annotations and fixes the join column name. But Steve should get all the merits 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);
        }
    }
}
like image 40
Janning Avatar answered Dec 02 '22 11:12

Janning


Here's a 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, e.g. log it.)
    }

    // The property holder path holds the owning entity's 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());
}
like image 131
Steve Chambers Avatar answered Dec 02 '22 11:12

Steve Chambers