hibernate
カスタムネーミング戦略
サーチ…
カスタムImplicitNamingStrategyの作成と使用
カスタムImplicitNamingStrategy
作成することで、Hibernateが、外部キー、一意キー、識別子列、基本列など、明示的でない名前のEntity
属性に名前を割り当てる方法を調整することができます。
たとえば、デフォルトでは、Hibernateはハッシュされた外部キーを生成し、次のようになります。
FKe6hidh4u0qh8y1ijy59s2ee6m
これはしばしば問題ではありませんが、そのような名前は、
FK_asset_tenant
これは、カスタムのImplicitNamingStrategy
で簡単に行うことができます。
この例ではImplicitNamingStrategyJpaCompliantImpl
拡張していますが、必要に応じてImplicitNamingStrategy
を実装することもできます。
import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.naming.ImplicitForeignKeyNameSource;
import org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl;
public class CustomNamingStrategy extends ImplicitNamingStrategyJpaCompliantImpl {
@Override
public Identifier determineForeignKeyName(ImplicitForeignKeyNameSource source) {
return toIdentifier("FK_" + source.getTableName().getCanonicalName() + "_" + source.getReferencedTableName().getCanonicalName(), source.getBuildingContext());
}
}
どのImplicitNamingStrategy
を使用するかをHibernateに指示するには、以下のように、 persistence.xml
またはhibernate.cfg.xml
ファイルのhibernate.implicit_naming_strategy
プロパティを定義します。
<property name="hibernate.implicit_naming_strategy"
value="com.example.foo.bar.CustomNamingStrategy"/>
あるいは、以下のようにhibernate.properties
ファイルでプロパティを指定することもできます:
hibernate.implicit_naming_strategy=com.example.foo.bar.CustomNamingStrategy
この例では、明示的に定義されたname
を持たないすべての外部キーが、 CustomNamingStrategy
から名前を取得するようになりました。
カスタム物理ネーミング戦略
私たちのエンティティをデータベースのテーブル名にマッピングするとき、私たちは@Table
アノテーションに依存します。しかし、データベーステーブル名の命名規則を持っている場合は、 @Table
アノテーションを明示的に記述することなく、エンティティの名前に基づいてテーブル名を計算するようにhibernateに指示するために、カスタムの物理命名戦略を実装できます。属性と列のマッピングも同じです。
たとえば、エンティティ名は次のとおりです。
ApplicationEventLog
私たちのテーブル名は:
application_event_log
私たちの物理的な命名戦略は、キャメルケースのエンティティ名からスネークケースのdbテーブル名に変換する必要があります。これを実現するには、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")
することができます: @Column(name="finish_dtl")