Hibernate HBM2DDL为主外键生成可为空的字段?

时间:2011-06-01 16:42:30

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

我正在使用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中的列'not null')。这是PricePK课程:

@Embeddable
public class PricePK implements Serializable {

    Integer product;

    Integer currency;
    ...etc...
}

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

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,金额   numeric(19,2)null,currency_id int   null,product_id int null,主键   (currency_id,product_id))不能   定义PRIMARY KEY约束   表'PRICE'中可以为空的列。

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

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

我发现您的映射有一些不太正确的地方:

  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

对此进行了测试