自定義物理命名策略
將我們的實體對映到資料庫表名時,我們依賴於 @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")