hibernate Sping Boot -乐观锁- java.sql.SQLIntegrityConstraintViolationException:列“order_id”不能为null

bweufnob  于 2023-10-23  发布在  Java
关注(0)|答案(1)|浏览(125)

我创建了一个使用乐观锁定的spring Boot 示例。我用Order方法调用时遇到问题。
当我调用排序方法时,我得到了如下所示的这个问题

java.sql.SQLIntegrityConstraintViolationException: Column 'order_id' cannot be null

我该如何解决?
这是下面显示的Book

@Entity
    @Data
    @EqualsAndHashCode(callSuper = true)
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    @Table(name = "BOOKS")
    public class Book extends BaseEntity {
    
        @Id
        @GeneratedValue(strategy = GenerationType.UUID)
        @Column(name = "ID")
        private String id;
    
        @Column(name = "ISBN")
        private String isbn;
    
        @Column(name = "NAME")
        private String name;
    
        @Column(name = "AUTHOER_FULL_NAME")
        private String authorFullName;
    
        @Column(name = "STOCK")
        private Integer stock;
    
        @Column(name = "PRICE")
        private BigDecimal price;
    
        @Version // Optimistic Locking
        private Long version;
    
    }

这里是下面显示的订单

@Entity
@Data
@EqualsAndHashCode(callSuper = true)
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "ORDERS")
public class Order extends BaseEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
    @JoinColumn(name = "userId", nullable = false)
    private User user;

    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    private Set<OrderItem> orderItems;

    public void add(OrderItem item){
        this.orderItems.add(item);
        item.setOrder(this);
    }
}

下面是OrderItem

@Entity
@Data
@EqualsAndHashCode(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "ORDER_ITEMS")
public class OrderItem extends BaseEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToOne
    @JoinColumn(name = "bookId")
    private Book book;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "orderId", referencedColumnName = "id", nullable = false)
    private Order order;
}

下面是OrderSaveServiceImpl方法

@Service
@RequiredArgsConstructor
public class OrderSaveServiceImpl implements OrderSaveService {

    private final OrderItemService orderItemService;

    private final UserService userService;

    private final OrderRepository orderRepository;

    private final Identity identity;

    @Transactional
    @Override
    public OrderDTO createOrder(CreateOrderRequest createOrderRequest) {

        CustomUserDetails customUserDetails = identity.getCustomUserDetails();

        User user = userService.findByEmail(customUserDetails.getEmail())
                .orElseThrow(() -> new UserNotFoundException(String.valueOf(customUserDetails.getId())));

        Set<OrderItemDTO> orderItemDTOs = createOrderRequest
                .getOrderDetailSet()
                .stream()
                .map(orderItemService::createOrderItem)
                .collect(Collectors.toSet());

        Order order = Order.builder()
                .user(user)
                .build();

        order.setOrderItems(OrderItemMapper.toOrderItemList(orderItemDTOs));

    orderItemDTOs.stream().forEach(orderItemDTO -> {
       order.add(OrderItemMapper.toOrderItem(orderItemDTO));
    });

        Order orderCompleted = orderRepository.save(order);

        return OrderMapper.toOrderDTO(orderCompleted);
    }
}

下面是OrderItemServiceImpl

@Service
@RequiredArgsConstructor
public class OrderItemServiceImpl implements OrderItemService {

    private final BookService bookService;

    @Retryable(retryFor = StockModifiedException.class, maxAttempts = 2, backoff = @Backoff(delay = 100))
    @Override
    public OrderItemDTO createOrderItem(OrderItemRequest orderDetailRequest) {

        final BookDTO bookDTO = bookService.getBookById(orderDetailRequest.getBookId());
        final Book book = BookMapper.toBook(bookDTO);

        boolean stockAvailable = bookService.isStockAvailable(bookDTO, orderDetailRequest.getAmount());

        if (stockAvailable) {

            final OrderItem orderItem = OrderItem.builder()
                    .book(book)
                    .build();

            BookUpdateStockRequest bookUpdateStockRequest = BookUpdateStockRequest.builder()
                    .stock(bookDTO.getStock() - orderDetailRequest.getAmount())
                    .build();

            bookService.updateBookStockById(bookDTO.getId(), bookUpdateStockRequest);

            return OrderItemMapper.toDTO(orderItem);
        }

        throw new StockModifiedException();
    }
}

下面是repo:Link

i34xakig

i34xakig1#

当然!下面是OrderSaveServiceImpl类中createOrder方法的修改版本,它确保在保存OrderItem实体之前在OrderItem实体中正确设置order_id列:

@Transactional
@Override
public OrderDTO createOrder(CreateOrderRequest createOrderRequest) {
    CustomUserDetails customUserDetails = identity.getCustomUserDetails();
    User user = userService.findByEmail(customUserDetails.getEmail())
            .orElseThrow(() -> new UserNotFoundException(String.valueOf(customUserDetails.getId())));

    Set<OrderItemDTO> orderItemDTOs = createOrderRequest.getOrderDetailSet()
            .stream()
            .map(orderItemService::createOrderItem)
            .collect(Collectors.toSet());

    Order order = Order.builder()
            .user(user)
            .build();

    order.setOrderItems(OrderItemMapper.toOrderItemList(orderItemDTOs));

    // Save the Order entity first
    Order savedOrder = orderRepository.save(order);

    // Associate the saved Order with OrderItems and save them
    for (OrderItemDTO orderItemDTO : orderItemDTOs) {
        OrderItem orderItem = OrderItemMapper.toOrderItem(orderItemDTO);
        orderItem.setOrder(savedOrder);
        orderItemRepository.save(orderItem);
    }

    return OrderMapper.toOrderDTO(savedOrder);
}

代码已被修改,以确保保存的Order实体在保存它们之前与OrderItems相关联。它使用setOrder方法在每个OrderItem实体中设置Order对象。
此外,请确保正确配置了OrderOrderItem实体之间的Map。Order实体中的orderItems属性应将mappedBy属性设置为OrderItem实体中的相应字段。例如,如果OrderItem实体中Map到Order实体的字段名为order,则Map将为@OneToMany(mappedBy = "order")
通过确保OrderItem实体具有对Order实体的正确引用,您应该能够解决问题并避免Column 'order_id' cannot be null异常。

相关问题