java - 将 Hibernate 4.3 迁移到 5.2 - 缺少表

标签 java hibernate migration hibernate-4.x hibernate-5.x

我正在尝试从 Hibernate 4.3 迁移到 5.2。 我最终遇到的问题是以下实体结构:

@MappedSuperclass
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Post<T> {

    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(
            name = "post_tags",
            joinColumns = {@JoinColumn(name = "post")},
            inverseJoinColumns = {@JoinColumn(name = "tag")})
    @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
    private Set<Tag> tags = new HashSet<>();

    // ...
}


@Entity
@Table(name = "x_post")
public class XPost extends Post<X> {
    // ...
}


@Entity
@Table(name = "y_post")
public class YPost extends Post<Y> {
    // ...
}

在迁移之前生成了 4 个不同的表: x_posty_postx_post_tagsy_post_tags

现在,当我运行 hibernate 验证时,我得到了

Caused by: org.hibernate.tool.schema.spi.SchemaManagementException: Schema-validation: missing table [post_tags] at org.hibernate.tool.schema.internal.AbstractSchemaValidator.validateTable(AbstractSchemaValidator.java:121) at org.hibernate.tool.schema.internal.GroupedSchemaValidatorImpl.validateTables(GroupedSchemaValidatorImpl.java:42) at org.hibernate.tool.schema.internal.AbstractSchemaValidator.performValidation(AbstractSchemaValidator.java:89) at org.hibernate.tool.schema.internal.AbstractSchemaValidator.doValidation(AbstractSchemaValidator.java:68)...

所以 Hibernate 希望现在有表 post_tags 但我不明白为什么。

我怀疑问题与命名策略有关 - 以前我使用的是 ImprovedNamingStrategy 但迁移后我必须添加自定义 hibernate.physical_naming_strategy ,看起来像这样:

public class MyPhysicalNamingStrategy extends PhysicalNamingStrategyStandardImpl implements
        Serializable {

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

    @Override
    public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment context) {
        return Identifier.toIdentifier(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);
    }
}

更新[2018-01-25]:

如果我从 tags 字段中删除 @JoinTable(name = "post_tags") ,则表将按预期生成:x_posty_postx_post_tagsy_post_tags。如果我将其保留为上面示例中的样子,它只会生成 post_tags 表。

因此,删除 @JoinTable 似乎可以解决这种情况下的问题,但是如果我想让连接表名称独立于字段 tags (例如,如果我希望它是单数 - *_post_tag)我仍然需要使用 @JoinTable 这让我回到最初的问题。

最佳答案

JPA 规范没有指定在这种情况下应创建 2 个表。

所以,在我看来,如果您显式指定表名,那么 Hibernate 为什么要尝试更改它呢?

因此,Hibernate 5 的行为更加直观。现在,当您不指定 @JoinTable 并且 Hibernate 生成两个表而不是一个时,您有两种选择:

  1. 您可以从 @MappedSuperclass 中删除 @ManyToMany 并在实体 X 和 Y 中显式声明它。
  2. 您将 @MappedSuperclass 中的 @ManyToMany 保留下来,并提供一个自定义 PhysicalNamingStrategyStandardImpl 来尝试覆盖默认的 toPhysicalTableName code> 以考虑您在 @JoinTable 中提供的值。

关于java - 将 Hibernate 4.3 迁移到 5.2 - 缺少表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48404183/

相关文章:

java - Spring-Data-JPA ManyToMany 关系与额外列

java - 对于映射到数据库表的 bean,hibernate 中的默认继承策略是什么?

java - 映射 JoinColum 值而不是 JSON 中的关联

entity-framework - 如何在 Seed 中通过 AddOrUpdate 方法插入身份

焦点改变前的Java Swing调用方法

java - 基本的 bonjour java IP 地址解析

mysql - 甲骨文 - 错误 : 'ORA-01400: cannot insert NULL into

java - Weblogic 8.1 到 Websphere 8.5 迁移

java - 如何检查 double 值是否包含特殊字符

java - 如何避免 org.eclipse.swt.SWTException : Invalid thread access