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?
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.
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.
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.
ImprovedNamingStrategy , which will convert the mixed case names to the embedded underscores name .
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);
}
}
}
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());
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With