Hibernate 4 - > 5迁移:NamingStrategy更改,找不到表

时间:2016-03-10 11:25:19

标签: java spring hibernate wildfly hibernate-5.x

我想做什么

我尝试从WildFly 8.2.0迁移到WildFly 10.0.0,这意味着我已经(并希望)从Hibernate 4.3迁移到Hibernate 5.0。

设置

Java 8u40 
Spring 4.1.9 
SQL Server 2012
Wildfly 8.2.0 -> Wildfly 10.0.0 
Hibernate 4.3.6 -> Hibernate 5.0.7

我已经阅读了migration guide,并且点击了命名策略更改。我have read many questions关于此问题,但我的看法有点不同。 Hibernate抱怨找不到表:

INFO [o.h.Version] HHH000412: Hibernate Core {5.0.7.Final}
INFO [o.h.cfg.Environment] HHH000206: hibernate.properties not found
INFO [o.h.cfg.Environment] HHH000021: Bytecode provider name : javassist
INFO [o.h.annotations.common.Version] HCANN000001: Hibernate Commons Annotations {5.0.1.Final}
INFO [o.h.dialect.Dialect] HHH000400: Using dialect: org.hibernate.dialect.SQLServerDialect
INFO [o.h.envers.boot.internal.EnversServiceImpl] Envers integration enabled? : true
INFO [o.h.validator.internal.util.Version] HV000001: Hibernate Validator 5.2.3.Final
INFO [o.h.tool.hbm2ddl.SchemaValidator] HHH000229: Running schema validator
INFO [o.h.t.s.e.i.InformationExtractorJdbcDatabaseMetaDataImpl] HHH000262: Table not found: SEC_AUTHORIZATION_RULES
INFO [o.h.t.s.e.i.InformationExtractorJdbcDatabaseMetaDataImpl] HHH000262: Table not found: SEC_USER
More tables not found ...
INFO [o.h.hql.internal.QueryTranslatorFactoryInitiator] (ServerService Thread Pool -- 62) HHH000397: Using ASTQueryTranslatorFactory

当我切换到DEBUG日志时,我看到他将实体绑定到正确的数据库表:

DEBUG [o.h.c.a.EntityBinder] Bind entity com.company.user.User on table SEC_USER
DEBUG [o.h.c.Ejb3Column] Binding column: Ejb3Column{table=org.hibernate.mapping.Table(SEC_USER), mappingColumn=ID, insertable=true, updatable=true, unique=false}

对我来说奇怪的是该应用有效。在Table not found之后,它不会抱怨架构不正确。该应用程序工作。选择,插入,更新数据有效。

我通过它的spring-orm抽象配置了hibernate:

@Bean(name = "myEmf")
@DependsOn({"dataSource", "flyway"})
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() {
    LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
    em.setDataSource(dataSource());
    em.setPackagesToScan(new String[]{"com.company.**.*"});
    em.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
    em.setJpaProperties(additionalProperties());
    return em;
}

private Properties additionalProperties() {
  Properties propFile = propertiesFile();
  properties.setProperty("hibernate.hbm2ddl.auto", "validate");
  properties.setProperty("hibernate.dialect", "org.hibernate.dialect.SQLServer2012Dialect");
  properties.setProperty("hibernate.show_sql", "false");
  properties.setProperty("hibernate.format_sql", "true");
  properties.setProperty("hibernate.id.new_generator_mappings", "false");
  properties.setProperty("hibernate.use_sql_comments", "false");
  properties.setProperty("hibernate.implicit_naming_strategy", "legacy-jpa");
  return properties;
}

在这个correspoding实体中,我有明确命名的表名和列名:

@Entity
@Table(name = "SEC_USER")
public class User extends BaseEntity {

   @Column(name = "LOGIN", nullable = false, unique = true)
   private String login;

问题

  • 如何让这个表找不到日志消息消失?
  • 如果我有明确命名的表名,为什么会出现?
  • 为什么他不抱怨专栏名称?
  • 为什么他看似正常

我尝试了什么

  • 将Spring 4.1.9升级到4.2.5 says he has support for Hibernate 5
  • 根据this
  • hibernate.implicit_naming_strategy 设置为 legacy-jpa
  • 手动设置默认架构并分配角色db_owner。注意我以前从来没有这样做过hibernate 4。 enter image description here

  • 我已经调试了一些hibernate以及我在InformationExtractorJdbcDatabaseMetaDataImpl.java中发现的hibernate没有看到目录(无论是什么)和架构。在leat,我认为他应该看到架构。请参见下面的屏幕截图:目录和架构为空。 enter image description here

5 个答案:

答案 0 :(得分:5)

我正在弄清楚同样的问题,但使用jtds驱动程序。经过一些研究,我发现,hibernate使用SqlServerDialect使用sp_tables存储过程来查找表声明。在那个SP第二个参数是模式名称,所以,如果它是null表搜索工作正常,如果它是空字符串 - 不是。

Hibernate在两种情况下将此参数设置为null

  • 如果方言方法getNameQualifierSupport()返回NameQualifierSupport.CATALOG,但所有SqlServerDialects都返回null
  • 如果司机在“支持解决方案”中使用false支持解决方案,则可以使用'方法,但jtds会返回true

为了解决这个问题,我决定扩展SqlServer2012Dialect结束覆盖getNameQualifierSupport()方法。

public class SqlServer2012DialectWithCatalogOnly extends SQLServer2012Dialect {
    @Override
    public NameQualifierSupport getNameQualifierSupport() {
        return NameQualifierSupport.CATALOG;
    }
}

并将属性hibernate.dialect设置为新类org.company.SqlServer2012DialectWithCatalogOnly

希望这会有所帮助......

答案 1 :(得分:0)

从Hibernate 5开始,NamingStrategy的逻辑被分为两个概念:Implicit和Physical。您已正确设置隐式命名策略,但您尚未设置物理命名策略。 Hibernate没有提供兼容的,所以你必须自己创建一个:

public class LegacyPhysicalNamingStrategy implements PhysicalNamingStrategy {
    private final Pattern pattern = Pattern.compile("(\\p{Lower}+)(\\p{Upper}+)");
    public Identifier toPhysicalCatalogName(Identifier name, JdbcEnvironment jdbcEnvironment) {
        return convert(name);
    }

    public Identifier toPhysicalSequenceName(Identifier name, JdbcEnvironment jdbcEnvironmen) {
        return convert(name);
    }

    public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment jdbcEnvironmen) {
        return convert(name);
    }

    public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment jdbcEnvironmen) {
        return convert(name);
    }

    public Identifier toPhysicalSchemaName(Identifier name, JdbcEnvironment jdbcEnvironmen) {
        return convert(name);
    }

    private Identifier convert(Identifier identifier) {
        if (identifier == null || identifier.getText().trim().isEmpty()) {
            return identifier;
        }

        String text = identifier.getText();
        text =  pattern.matcher(text).replaceAll("$1_$2").toLowerCase();
        return Identifier.toIdentifier(text, identifier.isQuoted());
    }

}

通过将属性hibernate.physical_naming_strategy设置为上述类的完全限定类名来更改为使用此项。

答案 2 :(得分:0)

使用最新的SQL Server JDBC驱动程序解决了这个问题。 A从2012年开始有一个旧的。现在我下载并使用了来自https://www.microsoft.com/en-us/download/details.aspx?id=11774的最新JDBC 4.2(sqljdbc_4.2.6420.100_enu.exe - > sqljdbc42.jar),它开始工作了。我甚至可以恢复SQL用户的默认架构更改。

答案 3 :(得分:0)

我想你们都有兴趣知道,我已经记录下面的票:

https://hibernate.atlassian.net/browse/HHH-11424

将JTDS更新到microsoft JDBC驱动程序将为您提供一个实现Connection.getSchema()的驱动程序,显然, 将解决此问题。

但是,如果您确实更新了该驱动程序,并且您依赖default_schema来有效地更改引用的位置表(例如,它不会查看当前用户的默认“dbo”架构)如果没有提供自定义的SchemaNameResolver,我仍然会运气不好。

真正烦人的一点是,在验证期间永远不会应用implicitSchemaName。

答案 4 :(得分:0)

我有类似的问题,我以这种方式解决了:

jpaProperties.put("hibernate.hbm2ddl.jdbc_metadata_extraction_strategy", "individually")