具有复合主键的单向OneToMany不会保留

时间:2016-02-03 17:07:29

标签: java sql-server hibernate jpa

我有遗留数据库的ER关系(基于MS SQL Server,如下所示

enter image description here

我目前正在尝试将其转换为JPA 2.1样式的方式如下

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Orders implements Serializable {

    @Id
    @GeneratedValue
    @Column(name = "OrderNumber", nullable = false)
    private Integer orderNumber;

    @ElementCollection(fetch = FetchType.EAGER)
    @CollectionTable(
            name = "OrderHistory",
            joinColumns = {
                    @JoinColumn(name = "OrderNumber", referencedColumnName = "OrderNumber", nullable = false)
            }
    )
    private List<OrderHistory> orderHistory;

    ----Other properties, Getters and Setters

}


@Entity
@PrimaryKeyJoinColumn(name = "OrderNumber")
public class SpecialOrders extends Orders implements Serializable {

    @JoinColumn(name = "OrderNumber", referencedColumnName = "OrderNumber", nullable = false)
    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
    @Fetch(FetchMode.SELECT)
    @OrderBy("sequenceNumber ASC")
    private List<Items> items;

    ----Other properties, Getters and Setters
}


@Entity
@IdClass(ItemsPK.class)
public class Items implements Serializable {

    @Id
    @Column(name = "OrderNumber", nullable = false, insertable = false, updatable = false)
    private Integer orderNumber;

    @Id
    @Column(name = "SequenceNumber", nullable = false)
    private Integer sequenceNumber;


    @ElementCollection(fetch = FetchType.EAGER)
    @CollectionTable(
            name = "CustomOptions",
            joinColumns = {
                    @JoinColumn(name = "OrderNumber", referencedColumnName = "OrderNumber", nullable = false),
                    @JoinColumn(name = "SequenceNumber", referencedColumnName = "SequenceNumber", nullable = false)
            }
    )
    private List<CustomOptions> customOptions;  

    ----Other properties, Getters and Setters
}

@Entity
public class ItemsPK implements Serializable {

    @Id
    @Column(name = "OrderNumber", nullable = false, insertable = false, updatable = false)
    private Integer orderNumber;

    @Id
    @Column(name = "SequenceNumber", nullable = false)
    private Integer sequenceNumber;
        ----Getters and Setters
}


@Entity
@IdClass(CustomOptionsPK.class)
public class CustomOptions implements Serializable {

    @Id
    @Column(name = "OrderNumber", nullable = false, insertable = false, updatable = false)
    private Integer orderNumber;

    @Id
    @Column(name = "SequenceNumber", nullable = false)
    private Integer sequenceNumber;

    @Id
    @Column(name = "OptionNumber", nullable = false)
    private Integer optionNumber;   

    ----Other properties, Getters and Setters
}

public class CustomOptionsPK implements Serializable {

    @Id
    @Column(name = "OrderNumber", nullable = false, insertable = false, updatable = false)
    private Integer orderNumber;

    @Id
    @Column(name = "SequenceNumber", nullable = false)
    private Integer sequenceNumber;

    @Id
    @Column(name = "OptionNumber", nullable = false)
    private Integer optionNumber;   

    ----Getters and Setters
}

使用上面的代码,我看到hibernate在

下面
  1. 插入订单并获取OrderNumber的GeneratedId
  2. 使用上面检索的orderNumber插入SpecialOrders。
  3. 尝试INSERT到Items表,orderNumber中包含NULL值,然后失败,因为orderNumber是一个NOT NULL列。
  4. 随后,如果向Items表添加“Simple”主键并将orderNumber设为NULLable列,则会发生以下情况:

    1. 插入订单并获取OrderNumber的GeneratedId
    2. 使用上面检索的orderNumber插入SpecialOrders。
    3. INSERT到Items表中,orderNumber为NULL值,并获取Items表行的生成ID。
    4. 使用为Items检索的ID,使用parent的orderNumber更新Items表的行。
    5. 尝试INSERT到CustomOptions表中,orderNumber中包含NULL值,然后失败,因为orderNumber是一个NOT NULL列。
    6. 根据上述顺序,似乎:

      • 复合主键似乎无法正常工作或不受支持。
      • Hibernate通过发出INSERT后跟UPDATE而不仅仅是插入来低效地处理OneToMany关系。

      知道我的理解是否正确?修复此问题的唯一方法似乎是我需要删除复合主键并将其替换为简单主键。

0 个答案:

没有答案