【问题标题】:Hibernate One to Many IntegrityConstraint when adding child to existing parent将子级添加到现有父级时休眠一对多 IntegrityConstraint
【发布时间】:2019-01-19 14:44:27
【问题描述】:

我有一个 Hibernate + Spring Boot 应用程序,并且在通过添加子项来更新父项时收到 IntegrityConstraintViolationException。

数据库架构是:

table order (
  id (primary key auto generated),
);

table order_line (
  order_id (primary key + foreign key to order.id),
  order_line_id (primary key set manually set in the code),
)

在java中:

@Getter
@Setter
@Entity(name = "ORDER")
public class Order {
    @Id
    @GeneratedValue(strategy= GenerationType.AUTO)
    private Integer id;


@Getter
@Setter
@Entity(name = "ORDER_LINE")
public class OrderLine implements Serializable{
    @Id
    private Integer orderLineId;
    @Id
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(referencedColumnName = "id", columnDefinition = "Integer", insertable = false, updatable = false)
    private Order order;

要创建订单,我使用 JpaRepository 并按如下方式创建对象:

    Order order = new Order();
    order.setId(118); //This is an existing order ID which should be updated
    Set<OrderLine> orderLines = new HashSet<OrderLine>();

    OrderLine orderLine = new OrderLine();
    orderLine.setOrderLineId(0); //This is an existing order line
    orderLine.setOrder(order);
    orderLines.add(orderLine);

    orderLine = new OrderLine();
    orderLine.setOrderLineId(1); //This is a non-existing order line
    orderLine.setOrder(order);
    orderLines.add(orderLine);

    order.setOrderLines(orderLines);

    orderRepository.save(order);

for (OrderLine orderLine : order.getOrderLines()) {
    orderLine.setOrder(order);
}
orderRepository.save(order);

这段代码的作用是:

  • 创建一个包含 0、1 或更多子代的新父代(意思是,我没有设置 orderId)

  • 更新父字段和/或任何子字段(在上面的示例中,如果我不添加第二个 orderLine,一切正常)

  • 删除子行

但是不起作用的是向现有父级添加一行。这会导致以下异常:

com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: 列“ORDER_LINE_ID”不能为空 sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)

我看不懂,因为我可以清楚地看到每个OrderLine对象的orderLineId设置正确。

我做错了什么?

【问题讨论】:

  • 我不确定您如何在代码中为 OrderLine 对象设置主键。这部分似乎在这里丢失了。异常告诉您,该对象没有主键。手动策略而不是为您的 OrderLine 主键生成值是否有特定原因?
  • 您好 Jens,感谢您的回复。我编辑了问题以包括这部分。我对 orderLine 使用手动策略的原因是因为它也是需要在我的代码中确定的订单的“位置”。
  • 我也尝试添加一个单独的自动生成的主键,但 ManyToOne 仍然不起作用。它说 ORDER_ID 不能为空(事实并非如此)

标签: java hibernate jpa many-to-one hibernate-onetomany


【解决方案1】:

如果您想在 OrderLine 实体中同时拥有 order_id 和 order_line_id 作为复合键,您需要先创建一个@Embeddable

 @Embeddable
 public class OrderLinePK implements Serializable {
      private Integer orderId;
      private Integer orderLineId;
 } 

并在您的 OrderLine 实体中将其更改为

 @EmbeddedId
 private OrderLinePk pk;

 @MapsId("orderId")
 @ManyToOne
 private Order order;

现在每次您需要创建一个新的 OrderLine 时,您都必须创建一个主键对象并像这样分配 ID

 OrderLine orderLine = new OrderLine();
 OrderLinePK pk = new OrderLinePK();
 pk.setOrderLineId(11);
 orderLine.setPk(pk);
 orderLine.setOrder(order);

希望这会有所帮助。

【讨论】:

  • 非常感谢!现在工作
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-21
  • 1970-01-01
  • 2015-08-07
  • 1970-01-01
  • 2023-04-06
相关资源
最近更新 更多