【问题标题】:How to handle the ORA-00972: identifier is too long Exception with Hibernate 5 a Naming Strategy如何处理 ORA-00972:标识符太长 Hibernate 5 命名策略异常
【发布时间】:2016-07-25 10:36:36
【问题描述】:

所以我最近在使用 Oracle 和 Hibernate 时遇到了这个错误:

Caused by: java.sql.SQLSyntaxErrorException: ORA-00972: identifier is too long
    at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:450)
    at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:399)
    at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:1059)
    at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:522)
    at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:257)

经过一些谷歌搜索后,我来到了这些项目:

https://github.com/schauder/hibernate-naming-strategy-for-oracle(差不多9岁) https://code.google.com/archive/p/hibernate-naming-strategy-for-oracle/(不再维护)

但是这些都不适用于 Hibernate5。在 Hibernate5 中有 2 种新的命名策略 - 一种物理的和隐含的。你们有谁知道是否有一种 hibernate5 命名策略来克服 oracle 的 30 个字符限制?

【问题讨论】:

    标签: database oracle hibernate jdbc orm


    【解决方案1】:

    实际上,您可以自定义 Hibernate 5 映射物理命名策略的方式。例如,您可以编写以下PhysicalNamingStartegy

    public class OracleNamingStrategy extends PhysicalNamingStrategyStandardImpl {
    
        @Override
        public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment context) {
            Identifier original = super.toPhysicalColumnName(name, context);
            if(original.getText().length() > 30) {
                return Identifier.toIdentifier(original.getText().substring(0, 30), original.isQuoted());
            }
            return original;
        }
    }
    

    并将此命名策略作为配置属性提供:

    properties.put("hibernate.physical_naming_strategy", "com.vladmihalcea.book.hpjp.hibernate.naming.OracleNamingStrategy");
    

    考虑以下实体映射:

    @Entity(name = "Person")
    public static class Person  {
    
        @Id
        private Long personId;
    
        @ManyToOne
        private PersonAddress addressIsAVeryLongColumnThatExceedsThirtyCharacters;
    
        @ManyToOne
        private PersonLocation location;
    }
    

    Hibernate 只会像这样截断列大小:

    create table Person (personId number(19,0) not null, addressIsAVeryLongColumnThatEx number(19,0), location_id number(19,0), primary key (personId))
    

    GitHub 上提供的代码。

    【讨论】:

    • 我认为这不适用于@CollectionTable。我有以下声明:```` @CollectionTable(name = ("classification_attribute_name_lv"), joinColumns = { @JoinColumn(name = ("classification_attribute_pk")) }, index = { @Index(name = (("idx_" + "classification_attribute_name_lv"), columnList = ("classification_attribute_pk")) }, foreignKey = @ForeignKey(name = (("fk_"+ "classification_attribute_name_lv"))) ````
    • 它适用于基本类型。对于@CollectionTable,您需要提供一个hibernate.implicit_naming_strategy 配置属性来指定ImplicitNamingStrategy 的自定义实现。自定义实现必须覆盖determineCollectionTableName
    • 其实方法toPhysicalTableName似乎就够了。不幸的是,我也在那里指定了长索引名称:@CollectionTable(name = "classification_attribute_name_lv", joinColumns = @JoinColumn(name = "classification_attribute_pk"), indices = { @Index(name = "idx_classification_attribute_name_lv", columnList = "classification_attribute_pk") } 而这个@Index(name= 既不能用Implicit 也不能用PhysicalNaming 策略修剪:(
    • 与外键相同:@ForeignKey(name = "fk_" + NAME + "_delivery_address")。一旦定义了name=,就不能使用策略来缩小它。所以就我而言,我有 200 多个实体,自从我使用 mysql 以来,但现在客户想要 Oracle,所以我被困住了 :(
    猜你喜欢
    • 2012-12-22
    • 1970-01-01
    • 2020-07-15
    • 1970-01-01
    • 1970-01-01
    • 2011-11-17
    • 2011-02-16
    • 2012-07-09
    • 1970-01-01
    相关资源
    最近更新 更多