NamingStrategy в Hibernate 5, совместимый с Hibernate 4
В настоящее время мы пытаемся переместить наше веб-приложение с Wildfly 9.0.2 на Wildfly 10.1.0 и переходим с Hibernate 4.3.10 на 5.0.10.
Мы никогда не определяли наши собственные NamingStrategy
используя любые имена, которые Hibernate выберет для наших сущностей (наша база данных Postgresql создается через hbm2ddl
).
Теперь, в Hibernate 5, у нас есть неизвестные ошибки столбцов, так как соглашение об именах изменилось. В частности, в таблицах соединений имена столбцов теперь основаны на истинном классе, а не на родительском: например, там, где мы имеем UserEntity
который наследует от AgentEntity
прежде чем мы получили agentEntity_id
колонка, теперь это userEntity_id
колонка.
Я пробую четыре существующих Hibernate ImplicitNamingStrategies
(jpa, legacy-jpa, legacy-hbm и component-path) в нашем persistence.xml
без успеха: каждый из них отличается от старой стратегии.
Итак, есть ли способ избежать переписывания моей собственной стратегии, чтобы сохранить соответствие нашей старой модели?
1 ответ
У меня была такая же проблема при переходе на Hibernate 5, хотя у нас есть серверная часть Oracle. Мне удалось достичь стратегии именования, аналогичной той, что была у меня в комплекте с Hibernate 4, используя оба org.hibernate.boot.model.naming.ImplicitNamingStrategy
а также org.hibernate.boot.model.naming.PhysicalNamingStrategy
,
Вот как выглядит определение моего компонента из контекста моего приложения:
@Bean
@Primary
public static JpaProperties jpaProperties() {
final Map<String, String> hibernateConfig = newHashMap();
hibernateConfig.put("hibernate.implicit_naming_strategy",
"org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyHbmImpl");
hibernateConfig.put("hibernate.physical_naming_strategy",
"com.anyapp.CustomNamingStrategy");
final JpaProperties jpaProperties = new JpaProperties();
jpaProperties.setProperties(hibernateConfig);
jpaProperties.setDatabase(ORACLE);
jpaProperties.setDatabasePlatform(ORACLE12C_DIALECT);
jpaProperties.setGenerateDdl(false);
jpaProperties.setShowSql(false);
return jpaProperties;
}
Самым раздражающим было выяснить, какие стратегии именования применять, каким образом и что мне пришлось реализовать CustomNamingStrategy
сам по себе, так как Hibernate не обеспечивает PhysicalNamingStrategy
что соответствует названию наследия ImprovedNamingStrategy
,
Вот содержимое моего CustomNamingStrategy
:
package com.anyapp;
import org.apache.commons.lang.StringUtils;
import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
public class CustomNamingStrategy implements PhysicalNamingStrategy {
@Override
public Identifier toPhysicalCatalogName(Identifier identifier, JdbcEnvironment jdbcEnv) {
return convert(identifier);
}
@Override
public Identifier toPhysicalColumnName(Identifier identifier, JdbcEnvironment jdbcEnv) {
return convert(identifier);
}
@Override
public Identifier toPhysicalSchemaName(Identifier identifier, JdbcEnvironment jdbcEnv) {
return convert(identifier);
}
@Override
public Identifier toPhysicalSequenceName(Identifier identifier, JdbcEnvironment jdbcEnv) {
return convert(identifier);
}
@Override
public Identifier toPhysicalTableName(Identifier identifier, JdbcEnvironment jdbcEnv) {
return convert(identifier);
}
private Identifier convert(Identifier identifier) {
if (identifier == null || StringUtils.isBlank(identifier.getText())) {
return identifier;
}
String regex = "([a-z])([A-Z])";
String replacement = "$1_$2";
String newName = identifier.getText().replaceAll(regex, replacement).toLowerCase();
return Identifier.toIdentifier(newName);
}
}
Возможно, вам придется настроить регулярное выражение в соответствии с вашими потребностями, но это то, что сработало для меня.