自定义物理命名策略
将我们的实体映射到数据库表名时,我们依赖于 @Table
注释。但是如果我们有数据库表名的命名约定,我们可以实现一个自定义的物理命名策略,以告诉 hibernate 根据实体的名称计算表名,而不用 @Table
注释明确说明这些名称。属性和列映射也是如此。
例如,我们的实体名称是:
ApplicationEventLog
我们的表名是:
application_event_log
我们的物理命名策略需要从 camel case 的实体名称转换为我们的 db 表名称,这些名称是 snake case。我们可以通过扩展 hibernate 的 PhysicalNamingStrategyStandardImpl
来实现这个目标:
import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
public class PhysicalNamingStrategyImpl extends PhysicalNamingStrategyStandardImpl {
private static final long serialVersionUID = 1L;
public static final PhysicalNamingStrategyImpl INSTANCE = new PhysicalNamingStrategyImpl();
@Override
public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment context) {
return new Identifier(addUnderscores(name.getText()), name.isQuoted());
}
@Override
public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment context) {
return new Identifier(addUnderscores(name.getText()), name.isQuoted());
}
protected static String addUnderscores(String name) {
final StringBuilder buf = new StringBuilder(name);
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++, '_');
}
}
return buf.toString().toLowerCase(Locale.ROOT);
}
}
我们正在重写方法 toPhysicalTableName
和 toPhysicalColumnName
的默认行为以应用我们的数据库命名约定。
为了使用我们的自定义实现,我们需要定义 hibernate.physical_naming_strategy
属性并将其命名为 PhysicalNamingStrategyImpl
类。
hibernate.physical_naming_strategy=com.example.foo.bar.PhysicalNamingStrategyImpl
这样我们就可以从 @Table
和 @Column
注释中减轻代码,所以我们的实体类:
@Entity
public class ApplicationEventLog {
private Date startTimestamp;
private String logUser;
private Integer eventSuccess;
@Column(name="finish_dtl")
private String finishDetails;
}
将正确映射到 db 表:
CREATE TABLE application_event_log (
...
start_timestamp timestamp,
log_user varchar(255),
event_success int(11),
finish_dtl varchar(2000),
...
)
如上例所示,由于某些原因,我们仍然可以根据我们的一般命名约定明确说明 db 对象的名称:@Column(name="finish_dtl")