Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/365.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 改进的命名策略在Hibernate 5中不再有效_Java_Hibernate_Jpa_Spring Data Jpa_Hibernate 5.x - Fatal编程技术网

Java 改进的命名策略在Hibernate 5中不再有效

Java 改进的命名策略在Hibernate 5中不再有效,java,hibernate,jpa,spring-data-jpa,hibernate-5.x,Java,Hibernate,Jpa,Spring Data Jpa,Hibernate 5.x,我有一个简单的spring jpa配置,其中配置了Hibernate的改进的命名策略。这意味着如果我的实体类有一个变量userName,那么Hibernate应该将其转换为user\u name,以查询数据库。但是在我升级到Hibernate 5之后,这个命名转换就停止了。我得到一个错误: 错误:“字段列表”中的未知列“user0\u0.userName” 这是我的Hibernate配置: @Configuration @EnableJpaRepositories("com.springJpa.

我有一个简单的spring jpa配置,其中配置了Hibernate的
改进的命名策略
。这意味着如果我的实体类有一个变量
userName
,那么Hibernate应该将其转换为
user\u name
,以查询数据库。但是在我升级到Hibernate 5之后,这个命名转换就停止了。我得到一个错误:

错误:“字段列表”中的未知列“user0\u0.userName”

这是我的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();
    }
}
这是我的实体类:

@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;

}
我不想在@Column注释中显式命名我的数据库字段。我希望我的配置可以隐式地将大小写转换为下划线


请指导。

刚刚解决了问题,当使用Hibernate版本<5.0时,配置绝对正确,但对于Hibernate>=5.0时,配置绝对正确

我在Spring4.2.0.RELEASE中使用Hibernate5.0.0.Final。我想Hibernate5与Spring4.2并不完全兼容。我刚刚将Hibernate降级到4.2.1.Final,一切都很顺利


Hibernate的
NamingStrategy
类在Hibernate 5中被弃用。

感谢您发布自己的解决方案。设置Hibernate 5命名策略对我帮助很大

hibernate 5.0之前版本的
hibernate.ejb.naming\u策略属性似乎分为两部分:

  • hibernate.物理命名策略
  • hibernate.隐式命名策略
这些属性的值不像
hibernate.ejb.naming_策略
那样实现
NamingStrategy
接口。有两个用于这些目的的新接口:

  • org.hibernate.boot.model.naming.PhysicalNamingStrategy
  • org.hibernate.boot.model.naming.ImplicitNamingStrategy
Hibernate 5只提供一个假定物理标识符名称与逻辑标识符名称相同的
PhysicalNamingStrategy
physicalnamingstrategstandardimpl
)实现

有几种
ImplicitNamingStrategy
的实现,但我发现没有一种与旧的
ImprovedNamingStrategy
相当。(请参阅:
org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyHbmImpl

因此,我实现了自己的
物理命名策略
,非常简单:

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);
 }
}
将Hibernate 5命名策略设置为以前的版本设置是一个陷阱

希望这有助于:

hibernate.implicit_naming_策略=…implicit命名策略 hibernate.physical_naming_strategy=..PhysicalNamingStrategyImpl

下面是代码(刚刚从现有代码中重新排列):

import java.io.Serializable;
导入java.util.Locale;
导入org.hibernate.boot.model.naming.Identifier;
导入org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl;
导入org.hibernate.engine.jdbc.env.spi.jdbc环境;
公共类PhysicalNamingStrategyImpl扩展PhysicalNamingStrategyStandImpl实现可序列化{
public static final PhysicalNamingStrategyImpl实例=新PhysicalNamingStrategyImpl();
@凌驾
公共标识符TopPhysicalTableName(标识符名称,JdbcEnvironment上下文){
返回新标识符(add下划线(name.getText()),name.isQuoted());
}
@凌驾
公共标识符TopPhysicalColumnName(标识符名称,JdbcEnvironment上下文){
返回新标识符(add下划线(name.getText()),name.isQuoted());
}
受保护的静态字符串添加下划线(字符串名称){
最终StringBuilder buf=新StringBuilder(名称.替换('.','.');
对于(inti=1;i感谢和+1感谢Samuel Andrés给出了非常有用的答案,但是避免手写的蛇壳逻辑可能是个好主意

它假定您的实体名称是用
StandardJavaClassFormat
编写的,列名是用
standardJavaFieldFormat

希望这能为将来来这里的人节省一些谷歌搜索的时间:-)


谢谢你的帖子。升级打破了表和列名策略。与其从
ImprovedNamingStrategy
复制逻辑,还可以使用委派

public class TableNamingStrategy extends PhysicalNamingStrategyStandardImpl {
    private static final String TABLE_PREFIX = "APP_";
    private static final long serialVersionUID = 1L;
    private static final ImprovedNamingStrategy STRATEGY_INSTANCE = new ImprovedNamingStrategy();

    @Override
    public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment context) {
        return new Identifier(classToTableName(name.getText()), name.isQuoted());
    }

    @Override
    public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment context) {
        return new Identifier(STRATEGY_INSTANCE.classToTableName(name.getText()), name.isQuoted());
    }

    private String classToTableName(String className) {
        return STRATEGY_INSTANCE.classToTableName(TABLE_PREFIX + className);
    }
}

没有番石榴和阿帕奇乌提斯

public class PhysicalNamingStrategyImpl extends PhysicalNamingStrategyStandardImpl {

    public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment context) {
        return context.getIdentifierHelper().toIdentifier(
                name.getText().replaceAll("((?!^)[^_])([A-Z])", "$1_$2").toLowerCase(),
                name.isQuoted()
        );
    }

    public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment context) {
        return context.getIdentifierHelper().toIdentifier(
                name.getText().replaceAll("((?!^)[^_])([A-Z])", "$1_$2").toLowerCase(),
                name.isQuoted()
        );
    }
}

每个答案都通过实现
PhysicalNamingStrategy
发布解决方案,但您所需要(也应该做)的就是实现
ImplicitNamingStrategy

当实体未显式命名其映射到的数据库表时,我们需要隐式确定该表名。或者,当特定属性未显式命名其映射到的数据库列时,我们需要隐式确定该列名。下面是org.hibernate.boot.model.naming.Implicit角色的示例NamingStrategy协定在映射未提供显式名称时确定逻辑名称

代码可以这么简单(使用原始的
添加下划线
和其他答案一样):

公共类ImplicitNamingStrategyImpl扩展了implicitnamingstrategyjpacomplianimpl{
@凌驾
受保护的标识符到标识符(字符串stringForm、MetadataBuildingContext buildingContext){
返回super.toIdentifier(添加下划线(stringForm),buildingContext);
}
受保护的静态字符串添加下划线(字符串名称){
最终StringBuilder buf=新StringBuilder(名称.替换('.','.');
对于(int i=1;i
我不明白您为什么不想使用@Column@Tyler这只是为了e
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()
    );
  }
}
public class TableNamingStrategy extends PhysicalNamingStrategyStandardImpl {
    private static final String TABLE_PREFIX = "APP_";
    private static final long serialVersionUID = 1L;
    private static final ImprovedNamingStrategy STRATEGY_INSTANCE = new ImprovedNamingStrategy();

    @Override
    public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment context) {
        return new Identifier(classToTableName(name.getText()), name.isQuoted());
    }

    @Override
    public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment context) {
        return new Identifier(STRATEGY_INSTANCE.classToTableName(name.getText()), name.isQuoted());
    }

    private String classToTableName(String className) {
        return STRATEGY_INSTANCE.classToTableName(TABLE_PREFIX + className);
    }
}
public class PhysicalNamingStrategyImpl extends PhysicalNamingStrategyStandardImpl {

    public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment context) {
        return context.getIdentifierHelper().toIdentifier(
                name.getText().replaceAll("((?!^)[^_])([A-Z])", "$1_$2").toLowerCase(),
                name.isQuoted()
        );
    }

    public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment context) {
        return context.getIdentifierHelper().toIdentifier(
                name.getText().replaceAll("((?!^)[^_])([A-Z])", "$1_$2").toLowerCase(),
                name.isQuoted()
        );
    }
}
public class ImplicitNamingStrategyImpl extends ImplicitNamingStrategyJpaCompliantImpl {

    @Override
    protected Identifier toIdentifier(String stringForm, MetadataBuildingContext buildingContext) {
        return super.toIdentifier(addUnderscores(stringForm), buildingContext);
    }

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