【问题标题】:Hibernate HBM2DDL produces nullable field for primary foreign key?Hibernate HBM2DDL 为主外键生成可为空的字段?
【发布时间】:2011-09-06 11:28:10
【问题描述】:

我正在使用 hbm2ddl(来自 hibernate3-maven-plugin 2.2)基于我的 JPA 注释实体生成 DDL。通常,这可以正常工作,但我最近介绍了一个使用由两个外键组成的复合键的实体,这导致 DDL 生成出现问题。

具体来说,生成的 DDL 指定主键列可以为空,而主键列不应该是这种情况。结果,MSSQL 无法创建主键约束,因为该列可以为空。

这里是实体

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@IdClass(PricePK.class)
public class Price extends PersistentEntity {

    @Id
    @ManyToOne(optional = false)
    private Product product;

    @Id
    @ManyToOne(optional = false)
    private Currency currency;

    @Column(nullable = false)
    private BigDecimal amount;
    ...etc...
}

该实体指定它使用 PricePK 作为其主键类,更重要的是,构成主键的两个 ManyToOne 实体不是可选的(这应该意味着 DDL 中的列“不为空”)。这是 PricePK 类:

@Embeddable
public class PricePK implements Serializable {

    Integer product;

    Integer currency;
    ...etc...
}

为 Price 表生成的 DDL 如下 - 注意 currency_id 和 product_id 都允许为空:

create table PRICE (
    version int null,
    amount numeric(19,2) not null,
    currency_id int null,
    product_id int null,
    primary key (currency_id, product_id)
);

当我尝试在 MSSql 中运行脚本时,出现以下(并不奇怪)错误:

不成功:创建表 store.PRICE (版本int null,金额 数字(19,2) null,currency_id int null, product_id int null, 主键 (currency_id, product_id)) 不能 定义 PRIMARY KEY 约束 表 'PRICE' 中的可为空列。

知道为什么正在生成的 DDL 为这两个外键列指定“null”吗?

【问题讨论】:

标签: java hibernate jpa hbm2ddl composite-primary-key


【解决方案1】:

您可能可以通过在 PricePK 的字段/getter 上使用 @Column(nullable = false) 的某些变体来解决此问题。

【讨论】:

    【解决方案2】:

    我可以看到您的映射不太正确:

    1. 不需要@Embeddable@IdClass
    2. 键应该引用实体而不是实体 id

    当我将映射更改为:

        @Entity
        @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
        @IdClass(PricePK.class)
        public class Price {
    
            @Id
            @ManyToOne(optional = false)
            Product product;
    
            @Id
            @ManyToOne(optional = false)
            Currency currency;
    
            @Column(nullable = false)
            BigDecimal amount;
        }
    
    
        public class PricePK implements Serializable {
    
            Product product;
    
            Currency currency;
    
            @Override
            public boolean equals(Object o) {
                if ( this == o ) {
                    return true;
                }
                if ( o == null || getClass() != o.getClass() ) {
                    return false;
                }
                PricePK pricePK = (PricePK) o;
                return Objects.equals( product, pricePK.product ) && Objects.equals(
                        currency,
                        pricePK.currency
                );
            }
    

    这些是用于创建表的查询:

        create table Price (
            amount numeric(19,2) not null,
            product_id numeric(19,0) not null,
            currency_id numeric(19,0) not null,
            primary key (currency_id, product_id)
        )
        
      
        alter table Price 
           add constraint FKbd5rb0nj1jehdn4x7fu01rk7n 
           foreign key (product_id) 
           references Product
    
        alter table Price 
           add constraint FKb5kubh6h82dbyovrtcuby54d2 
           foreign key (currency_id) 
           references Currency
    

    我已经用 Hibernate ORM 5.5.0.Final 和方言org.hibernate.dialect.SQLServerDialect对此进行了测试

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-05
      • 2019-03-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多