Hibernate один ко многим IntegrityConstraint при добавлении дочернего элемента к существующему родителю - PullRequest
0 голосов
/ 19 января 2019

У меня есть приложение 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);

Что работает в этом коде:

  • Создание нового родителя (то есть я не устанавливаю orderId) с 0, 1 или более дочерними элементами

  • Обновление родительских полей и / или любого из дочерних элементов (в приведенном выше примере все работает нормально, если я не добавляю второй orderLine)

  • Удаление дочерних строк

Но что не работает, так это добавление строки к существующему родителю. Это приводит к следующему исключению:

com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Столбец 'ORDER_LINE_ID' не может быть пустым в sun.reflect.NativeConstructorAccessorImpl.newInstance0 (собственный метод)

что я не понимаю, потому что я ясно вижу, что orderLineId каждого из объектов OrderLine установлен правильно.

Что я делаю не так?

1 Ответ

0 голосов
/ 21 января 2019

Если вы хотите, чтобы и order_id, и order_line_id были составным ключом в сущности OrderLine, вам нужно сначала создать @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, вы должны создать объект первичного ключа и назначить идентификатор, подобный этому

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

надеюсь, это поможет.

...