Spring boot - 乐观锁 - java.sql.SQLIntegrityConstraintViolationException:列“order_id”不能为空

问题描述 投票:0回答:1

我创建了一个使用乐观锁定的 Spring Boot 示例。我在使用 createOrder 方法调用时遇到问题。

当我调用 createOrder 方法时,我遇到了如下所示的问题

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

我该如何修复它?

这是下面所示的

    @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(); } }
这是回购协议:

链接

java spring-boot hibernate dto optimistic-locking
1个回答
0
投票
当然!以下是

createOrder

 类中 
OrderSaveServiceImpl
 方法的修改版本,可确保在保存之前在 
order_id
 实体中正确设置 
OrderItem
 列:

@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

 相关联。它使用 
Order
 方法在每个 
OrderItem
 实体中设置 
setOrder
 对象。

此外,请确保正确配置

Order

OrderItem
 实体之间的映射。 
orderItems
 实体中的 
Order
 属性应将 
mappedBy
 属性设置为 
OrderItem
 实体中的适当字段。例如,如果 
OrderItem
 实体中映射到 
Order
 实体的字段名为 order,则映射将为 
@OneToMany(mappedBy = "order")

通过确保

OrderItem

 实体具有对 
Order
 实体的正确引用,您应该能够解决问题并避免 
Column 'order_id' cannot be null
 异常。

© www.soinside.com 2019 - 2024. All rights reserved.