ImprovedNamingStrategy ya no funciona en Hibernate 5

Tengo una configuración simple de spring-jpa donde he configurado Hibernate’s . Esto significa que si mi clase de entidad tiene una variable, Hibernate debería convertirla para consultar la base de datos. Pero esta conversión de nombres dejó de funcionar después de actualizar a Hibernate 5. Recibo el error:ImprovedNamingStrategyuserNameuser_name

ERROR: Columna desconocida ‘user0_.userName’ en ‘lista de campos’

Esta es mi configuración de Hibernate:

@Configuration
@EnableJpaRepositories("com.springJpa.repository")
@EnableTransactionManagement
public class DataConfig {

    @Bean
    public DataSource dataSource(){
        DriverManagerDataSource ds = new DriverManagerDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://localhost:3306/test");
        ds.setUsername("root");
        ds.setPassword("admin");
        return ds;
    }


    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(){ 

        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        vendorAdapter.setShowSql(Boolean.TRUE);
        vendorAdapter.setDatabase(Database.MYSQL);

        LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
        factory.setJpaVendorAdapter(vendorAdapter);
        factory.setDataSource(dataSource());
        factory.setPackagesToScan("com.springJpa.entity");


        Properties jpaProperties = new Properties();

        jpaProperties.put("hibernate.ejb.naming_strategy","org.hibernate.cfg.ImprovedNamingStrategy");
        jpaProperties.put("hibernate.dialect","org.hibernate.dialect.MySQL5InnoDBDialect");

        factory.setJpaProperties(jpaProperties);
        factory.afterPropertiesSet();
        return factory;
    }

    @Bean
    public SharedEntityManagerBean entityManager() {
        SharedEntityManagerBean entityManager = new SharedEntityManagerBean();
        entityManager.setEntityManagerFactory(entityManagerFactory().getObject());
        return entityManager;
    }



    @Bean
    public PlatformTransactionManager transactionManager() {
        JpaTransactionManager txManager = new JpaTransactionManager();
        txManager.setEntityManagerFactory(entityManagerFactory().getObject());
        return txManager;
    }

    @Bean
    public ImprovedNamingStrategy namingStrategy(){
        return new ImprovedNamingStrategy();
    }
}

Esta es mi clase Entity:

@Getter
@Setter
@Entity
@Table(name="user")
public class User{

    @Id
    @GeneratedValue
    private Long id;

    private String userName;
    private String email;
    private String password;
    private String role;

}

No quiero nombrar explícitamente los campos de mi base de datos dentro de las anotaciones @Column. Quiero mi configuración que puede convertir implícitamente la caja de camello en subrayado.

Por favor, guía.

Respuestas:8 Respuestas 8
Tiempo:hace 7 años
Última modificación:hace 9 meses

Solución

Gracias por publicar su propia solución. ¡Me ayuda mucho establecer la estrategia de nombres de Hibernate 5!

La propiedad de pre-Hibernate 5.0 parece dividida en dos partes:hibernate.ejb.naming_strategy

  • hibernate.physical_naming_strategy
  • hibernate.implicit_naming_strategy

Los valores de estas propiedades no implementan la interfaz como lo hizo . Hay dos nuevas interfaces para estos fines: NamingStrategyhibernate.ejb.naming_strategy

  • org.hibernate.boot.model.naming.PhysicalNamingStrategy
  • org.hibernate.boot.model.naming.ImplicitNamingStrategy

Hibernate 5 proporciona solo una implementación de () que asume que los nombres de identificadores físicos son los mismos que los lógicos.PhysicalNamingStrategyPhysicalNamingStrategyStandardImpl

Hay varias implementaciones de pero no encontré ninguna equivalente a la anterior. (Véase: ImplicitNamingStrategyImprovedNamingStrategyorg.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyHbmImpl)

Entonces, implementé el mío propio, que es muy simple:PhysicalNamingStrategy

public class PhysicalNamingStrategyImpl extends PhysicalNamingStrategyStandardImpl implements Serializable {

 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.replace('.', '_') );
     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);
 }
}

Tenga en cuenta que el método es del original .addUnderscores()org.hibernate.cfg.ImprovedNamingStrategy

Luego, establecí esta estrategia física en el archivo de persistencia.xml:

  <property name="hibernate.physical_naming_strategy" value="my.package.PhysicalNamingStrategyImpl" />

Es una trampa establecer la estrategia de nomenclatura Hibernate 5 como configuración de la versión anterior.

Otras respuestas

Thanks and +1 to Samuel Andrés for the very helpful answer, however it’s probably a good idea to avoid the hand-written snake-casing logic. Here is the same solution, using Guava.

It assumes your entity names are written in the and column names in the StandardJavaClassFormatstandardJavaFieldFormat

Hopefully this will save some people coming here in future some googling 🙂

import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import static com.google.common.base.CaseFormat.*;

public class SnakeCaseNamingStrategy extends PhysicalNamingStrategyStandardImpl {

  public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment context) {
    return new Identifier(
      UPPER_CAMEL.to(LOWER_UNDERSCORE, name.getText()),
      name.isQuoted()
    );
  }

  public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment context) {
    return new Identifier(
      LOWER_CAMEL.to(LOWER_UNDERSCORE, name.getText()),
      name.isQuoted()
    );
  }
}

Deja un comentario