2015-08-23 30 views
15

Piszę aplikację przy użyciu bazy danych PostgreSQL oraz wiosennych i hibernacyjnych frameworków.wiosna - hibernacja 5 konfiguracja strategii nazewnictwa

Uaktualniłem framework sprężynowy z wersji 4.1.5.RELEASE do wersji 4.2.0.RELEASE i zaktualizowałem platformę hibernacji z wersji 4.3.7.Final do wersji 5.0.0.Final.

Po aktualizacji mam problemy z NamingStrategy. W bazie danych Postgresql nazwy kolumn tabeli są pisane małymi literami, podkreślone, w warstwie aplikacji właściwości fasoli są w wielbidach.

ten pracuje plik konfiguracyjny wiosna dla starszej wersji:

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns="http://www.springframework.org/schema/beans" 
     xmlns:p="http://www.springframework.org/schema/p" 
     xmlns:context="http://www.springframework.org/schema/context" 
     xmlns:tx="http://www.springframework.org/schema/tx" 
     xsi:schemaLocation=" 
     http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans.xsd 
     http://www.springframework.org/schema/context 
     http://www.springframework.org/schema/context/spring-context.xsd 
     http://www.springframework.org/schema/tx 
     http://www.springframework.org/schema/tx/spring-tx.xsd"> 

    <context:component-scan base-package="fms" /> 

    <bean id="microFmsDataSource" class="org.apache.tomcat.jdbc.pool.DataSource" destroy-method="close"> 
     <property name="driverClassName" value="org.postgresql.Driver" /> 
     <property name="url" value="***" /> 
     <property name="username" value="***" /> 
     <property name="password" value="***" /> 

     <property name="testOnBorrow" value="true" /> 
     <property name="testOnReturn" value="true" /> 
     <property name="testWhileIdle" value="true" /> 
     <property name="validationQuery" value="select 1" /> 
     <property name="initialSize" value="5" /> 
     <property name="minIdle" value="10" /> 
     <property name="maxIdle" value="100" /> 
     <property name="maxActive" value="100" /> 
     <property name="removeAbandoned" value="true" /> 
    </bean> 

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
     <property name="dataSource" ref="microFmsDataSource"/> 

     <property name="packagesToScan"> 
      <list> 
       <value>fms</value> 
      </list> 
     </property> 

     <property name="jpaVendorAdapter"> 
      <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" /> 
     </property> 

     <property name="jpaPropertyMap"> 
      <map> 
       <entry key="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider" /> 
       <entry key="hibernate.hbm2ddl.auto" value="validate" /> 
       <entry key="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" /> 
       <entry key="hibernate.show_sql" value="true" /> 
       <entry key="hibernate.format_sql" value="true" /> 
       <entry key="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy" /> 
      </map> 
     </property> 
    </bean> 

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
     <property name="entityManagerFactory" ref="entityManagerFactory" /> 
    </bean> 

    <tx:annotation-driven transaction-manager="transactionManager"/> 
</beans> 

Po uaktualnieniu Zmieniłem konfigurację NamingStrategy:

<entry key="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy" /> 

tak:

<entry key="hibernate.implicit_naming_strategy" value="***" /> 

i próbował wszystkich wariantów opcje wymienione w hibernacji javadoc: https://docs.jboss.org/hibernate/orm/5.0/javadocs/org/hibernate/cfg/AvailableSettings.html#IMPLICIT_NAMING_STRATEGY

ale bez powodzenia.

Czy możesz mi powiedzieć, co jest alternatywą ImprovedNamingStrategy w Hibernate 5 i podać działający przykład konfiguracji?

+0

użyłem hibernate.implicit_naming_strategy legacy-WZP i to działało dla mnie. Możesz spróbować ? – Sharadr

+0

Prawdopodobny duplikat [ImprovedNamingStrategy już nie działa w Hibernate 5] (http://stackoverflow.com/questions/32437202/improvednamstrategy-no-longer-working-in-hibernate-5) – Rich

Odpowiedz

24

Myślę, że znalazłem rozwiązanie.

Aby osiągnąć mój cel, użyłem konfiguracji hibernate.physical_naming_strategy zamiast hibernate.implicit_naming_strategy.

Stworzyłem implementację interfejsu PhysicalNamingStrategy który symuluje część funkcjonalności oryginalnego ImprovedNamingStrategy Klasa:

package fms.util.hibernate; 

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 ImprovedNamingStrategy 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); 
    } 
} 

Po Stworzyłem tę klasę, zmieniłem konfigurację z:

<entry key="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy" /> 

do tego:

<entry key="hibernate.physical_naming_strategy" value="fms.util.hibernate.ImprovedNamingStrategy" /> 

i teraz wszystko działa poprawnie.

Rozwiązanie to obejmuje tylko niewielką część ImprovedNamingStrategy. W moim projekcie do mapowania tabeli i dołączania mapowania jawnie określam nazwę tabeli lub kolumny łączenia. Opieram się na niejawnej konwersji nazwy tylko dla nazw kolumn. To proste rozwiązanie było dla mnie do przyjęcia.

Jest to pełny przykład mojego pliku konfiguracyjnego Wiosna:

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns="http://www.springframework.org/schema/beans" 
     xmlns:p="http://www.springframework.org/schema/p" 
     xmlns:context="http://www.springframework.org/schema/context" 
     xmlns:tx="http://www.springframework.org/schema/tx" 
     xsi:schemaLocation=" 
     http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans.xsd 
     http://www.springframework.org/schema/context 
     http://www.springframework.org/schema/context/spring-context.xsd 
     http://www.springframework.org/schema/tx 
     http://www.springframework.org/schema/tx/spring-tx.xsd"> 

    <context:component-scan base-package="fms" /> 

    <bean id="microFmsDataSource" class="org.apache.tomcat.jdbc.pool.DataSource" destroy-method="close"> 
     <property name="driverClassName" value="org.postgresql.Driver" /> 
     <property name="url" value="***" /> 
     <property name="username" value="***" /> 
     <property name="password" value="***" /> 

     <property name="testOnBorrow" value="true" /> 
     <property name="testOnReturn" value="true" /> 
     <property name="testWhileIdle" value="true" /> 
     <property name="validationQuery" value="select 1" /> 
     <property name="initialSize" value="5" /> 
     <property name="minIdle" value="10" /> 
     <property name="maxIdle" value="100" /> 
     <property name="maxActive" value="100" /> 
     <property name="removeAbandoned" value="true" /> 
    </bean> 

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
     <property name="dataSource" ref="microFmsDataSource"/> 

     <property name="packagesToScan"> 
      <list> 
       <value>fms</value> 
      </list> 
     </property> 

     <property name="jpaVendorAdapter"> 
      <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" /> 
     </property> 

     <property name="jpaPropertyMap"> 
      <map> 
       <entry key="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider" /> 
       <entry key="hibernate.hbm2ddl.auto" value="validate" /> 
       <entry key="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" /> 
       <entry key="hibernate.show_sql" value="true" /> 
       <entry key="hibernate.format_sql" value="true" /> 
       <entry key="hibernate.physical_naming_strategy" value="fms.util.hibernate.ImprovedNamingStrategy" /> 
      </map> 
     </property> 
    </bean> 

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
     <property name="entityManagerFactory" ref="entityManagerFactory" /> 
    </bean> 

    <tx:annotation-driven transaction-manager="transactionManager"/> 
</beans> 

Mam nadzieję, że to rozwiązanie będzie pomocne dla kogoś. :)

+1

Dzięki za udostępnienie. Właśnie wpadłem na ten problem. Twoje rozwiązanie nie działa dla mnie. Naprawia tylko camelcase => podkreślenie. Nie rozwiązuje to drugiej różnicy między standardem ImprovedNamingStrategy a standardem JPA, a mianowicie sufiksem _id. Standard tworzy przyrostek _id na kolumnach kluczy obcych, na które ImporvedNamingStrategy nie ma. Czy masz na to również poprawkę? –

+0

@ AleksanderBlomskøld Masz rację, to rozwiązanie obejmuje tylko niewielką część ImprovedNamingStrategy. W moim projekcie do mapowania tabeli i dołączania mapowania jawnie określam nazwę tabeli lub kolumny łączenia. Opieram się na niejawnej konwersji nazwy tylko dla nazw kolumn. To proste rozwiązanie było dla mnie do przyjęcia. – Yoh0xFF

+1

Niepoprawne jest powiedzenie "Dla zadania, które chcę wykonać, musi być używana" hibernate.physical_naming_strategy "konfiguracja". Ten sam efekt można osiągnąć, stosując implementację 'ImplicitNamingStrategy'. "nie ma implementacji interfejsu PhysicalNamingStrategy" jest również niepoprawne, patrz [PhysicalNamingStrategyStandardImpl] (https://docs.jboss.org/hibernate/orm/5.0/javadocs/index.html?org/hibernate/boot/model/naming/PhysicalNamingStrategyStandardImpl .html) jako przykład. –

-1

Pełna Wiosna config, który działa dla mnie:

<property name="dataSource" ref="dataSource"/> 
    <property name="jpaVendorAdapter"> 
     <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> 
      <property name="database" value="${db.platform}"/> 
      <property name="generateDdl" value="false"/> 
     </bean> 
    </property> 
    <property name="jpaProperties"> 
     <props> 
      <!--<prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>--> 
      <prop key="hibernate.implicit_naming_strategy">org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyHbmImpl</prop> 
      <prop key="hibernate.format_sql">${hibernate.format_sql:false}</prop> 
      <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto:validate}</prop> 
      <prop key="hibernate.show_sql">${hibernate.show_sql:false}</prop> 
      <prop key="hibernate.use_sql_comments">${hibernate.use_sql_comments:false}</prop> 
      <prop key="hibernate.id.new_generator_mappings">${hibernate.id.new_generator_mappings:true}</prop> 
      <prop key="hibernate.enable_lazy_load_no_trans">${hibernate.enable_lazy_load_no_trans:true}</prop> 
      <prop key="hibernate.max_fetch_depth">${hibernate.max_fetch_depth:1}</prop> 
      <prop key="hibernate.default_batch_fetch_size">${hibernate.default_batch_fetch_size:16}</prop> 
     </props> 
    </property> 
</bean> 
0

spróbuj tego:

@Bean 
public LocalSessionFactoryBean getSessionFactory() { 
    LocalSessionFactoryBean localSessionFactoryBean = new LocalSessionFactoryBean(); 
    localSessionFactoryBean.setDataSource(getDataSource()); 
    localSessionFactoryBean.setHibernateProperties(getHibernateProperties()); 
    localSessionFactoryBean.setPackagesToScan(new String[]{"com.xxx.pojo"}); 
    // -----important----- 
    localSessionFactoryBean.setPhysicalNamingStrategy(new CustomNamingStrategy()); 
    return localSessionFactoryBean; 
} 

public class CustomNamingStrategy extends PhysicalNamingStrategyStandardImpl {***