QUESTION
I build a Spring-Boot application that accesses a Database and extracts data from it. Everything is working fine, but I want to configure the table names from an external .properties file like:
@Entity
@Table(name = "${fleet.table.name}")
public class Fleet {
..
}
I tried to find something but I didn't. You can access external properties with the @Value("...")
annotation though.
So my question is: Is there any way I can configure the table names? Or can I change/intercept the query that is sent by Hibernate?
SOLUTION
Hibernate 5 provide the PhysicalNamingStrategy class to make it work. Just give your tables a placeholder name:
@Entity
@Table(name = "Fleet") // placeholder name that will be replaced by the custom naming strategy
public class Fleet {
...
}
// other tables like `Visits` and `Result`
And apply a custom PhysicalNamingStrategy
:
@Configuration
public class TableNameConfig{
@Value("${fleet.table.name}")
private String fleetTableName;
@Value("${visits.table.name}")
private String visitsTableName;
@Value("${route.table.name}")
private String routeTableName;
@Bean
public PhysicalNamingStrategyStandardImpl physicalNamingStrategyStandard() {
return new PhysicalNamingImpl();
}
static class PhysicalNamingImpl extends PhysicalNamingStrategyStandardImpl {
@Override
public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment context) {
return switch (name.getText()) {
case "Fleet" -> new Identifier(fleetTableName, name.isQuoted());
case "Visits" -> new Identifier(visitsTableName, name.isQuoted());
case "Result" -> new Identifier(routeTableName, name.isQuoted());
default -> super.toPhysicalTableName(name, context);
};
}
}
}
N.B. This Stackoverflow article on NamingStrategy gave me the idea.
Table names are really coming from hibernate itself via its strategy interfaces. Boot configures this as SpringNamingStrategy
and there were some changes in Boot 2.x how things can be customised. Worth to read gh-1525 where these changes were made. Configure Hibernate Naming Strategy has some more info.
There were some ideas to add some custom properties to configure SpringNamingStrategy
but we went with allowing easier customisation of a whole strategy beans as that allows users to to whatever they need to do.
AFAIK, there's no direct way to do config like you asked but I'd assume that if you create your own strategy you can then auto-wire you own properties to there. As in those customised strategy interfaces you will see the entity name, you could reserve a keyspace in boot's configuration properties to this and match entity names.
mytables.naming.fleet.name=foobar
mytables.naming.othertable.name=xxx
Your configuration properties would take mytables
and within that naming
would be a Map
. Then in your custom strategy it would simply be by checking from mapping table if you defined a custom name.