2015-08-23 20 views
15

Tôi đang viết ứng dụng bằng cách sử dụng cơ sở dữ liệu postgresql và khung công tác spring + hibernate.spring - hibernate 5 cấu hình đặt tên chiến lược

Tôi đã nâng cấp khung công tác mùa xuân từ phiên bản 4.1.5.RELEASE lên 4.2.0.RELEASE và nâng cấp khung ngủ đông từ 4.3.7.Final lên 5.0.0Phiên bản gốc.

Sau khi nâng cấp, tôi gặp sự cố với NamingStrategy. Trong cơ sở dữ liệu postgresql, các tên cột của bảng được viết bằng chữ thường được phân tách bằng dấu gạch dưới, trong lớp ứng dụng, các thuộc tính bean nằm trong thư mục camelcase.

Đây là hoạt động tập tin cấu hình mùa xuân cho phiên bản cũ:

<?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> 

Sau khi nâng cấp tôi đã thay đổi cấu hình NamingStrategy:

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

như thế này:

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

và thử tất cả các biến thể của các tùy chọn được liệt kê trong hibernate javadoc: https://docs.jboss.org/hibernate/orm/5.0/javadocs/org/hibernate/cfg/AvailableSettings.html#IMPLICIT_NAMING_STRATEGY

nhưng không thành công.

Bạn có thể cho tôi biết thay thế của ImprovedNamingStrategy trong Hibernate 5 và cung cấp ví dụ cấu hình hoạt động không?

+0

tôi đã sử dụng di sản-JPA và nó làm việc cho tôi. Bạn có thể thử ? – Sharadr

+0

Bản sao có thể có của [ImprovedNamingStrategy không còn hoạt động trong Hibernate 5] (http://stackoverflow.com/questions/32437202/improvednamingstrategy-no-longer-working-in-hibernate-5) – Rich

Trả lời

24

Tôi nghĩ tôi đã tìm được giải pháp.

Để đạt được mục tiêu của mình, tôi đã sử dụng cấu hình hibernate.physical_naming_strategy thay vì hibernate.implicit_naming_strategy.

Tôi tạo ra một thực hiện các giao diện PhysicalNamingStrategy mô phỏng một phần của các chức năng của bản gốc ImprovedNamingStrategy lớp:

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

Sau khi tôi tạo ra lớp học này, tôi đã thay đổi cấu hình của tôi từ:

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

này:

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

và bây giờ mọi thứ hoạt động chính xác.

Giải pháp này chỉ bao gồm một phần nhỏ của ImprovedNamingStrategy. Trong dự án của tôi, để lập bản đồ bảng và ánh xạ nối, tôi luôn chỉ rõ tên của bảng hoặc cột kết nối một cách rõ ràng. Tôi chỉ dựa vào chuyển đổi tên ngầm cho tên cột. Vì vậy, giải pháp đơn giản này đã được chấp nhận đối với tôi.

Đây là một ví dụ đầy đủ của tập tin cấu hình Spring tôi:

<?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> 

tôi hy vọng giải pháp này sẽ rất hữu ích cho ai đó. :)

+1

Cảm ơn bạn đã chia sẻ. Tôi chỉ gặp vấn đề này. Giải pháp của bạn không hiệu quả đối với tôi. Nó chỉ sửa camelcase => gạch dưới. Nó không sửa chữa sự khác biệt khác giữa ImprovedNamingStrategy và tiêu chuẩn JPA, cụ thể là _id-suffix. Tiêu chuẩn tạo ra một _id-hậu tố trên các cột chính nước ngoài, mà các ImporvedNamingStrategy không. Bạn có sửa chữa cho điều đó không? –

+0

@ AleksanderBlomskøld Bạn nói đúng, giải pháp này chỉ bao gồm một phần nhỏ của ImprovedNamingStrategy. Trong dự án của tôi, để lập bản đồ bảng và ánh xạ nối, tôi luôn chỉ rõ tên của bảng hoặc cột kết nối một cách rõ ràng. Tôi chỉ dựa vào chuyển đổi tên ngầm cho tên cột. Vì vậy, giải pháp đơn giản này đã được chấp nhận đối với tôi. – Yoh0xFF

+1

Không chính xác để nói 'Đối với tác vụ tôi muốn hoàn thành, phải được sử dụng "hibernate.physical_naming_strategy" configuration'. Hiệu ứng tương tự có thể đạt được bằng cách sử dụng 'ImplicitNamingStrategy'. 'không có triển khai thực hiện giao diện PhysicalNamingStrategy' là không chính xác quá xem [PhysicalNamingStrategyStandardImpl] (https://docs.jboss.org/hibernate/orm/5.0/javadocs/index.html?org/hibernate/boot/model/naming/PhysicalNamingStrategyStandardImpl .html) làm ví dụ. –

-1

Full cấu hình mùa xuân mà làm việc cho tôi:

<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

thử điều này:

@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 {*** 
Các vấn đề liên quan