我正在为餐厅预订系统开发一个 REST API 项目,该项目使用 Spring boot 和 HSQLDB,使用 Spring data JPA。该场景是用户可以调用预订服务来预订特定时间的餐 table 。在给定时间段内只能允许一次预订。
我的问题是如何处理 2 个或更多不同用户同时调用 REST API 以同时预订同一张 table 的情况。
我对此进行了搜索,发现乐观锁定可以用于此目的,但我不确定它在这种情况下有何帮助,除非我对餐厅表记录进行任何更新。
下面是我的项目结构。
预订 DAO
@Entity
public class Booking {
@Id
@GeneratedValue
private Long id;
private String bookingId;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm")
private LocalDateTime bookingStart;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm")
private LocalDateTime bookingEnd;
@OneToOne
private RestaurantTable table;
private String customerName;
..Setter/Getter
}
餐厅 DAO
@Entity
public class RestaurantTable {
@Id
@GeneratedValue
private Long id;
private Integer tableId;
private Integer capacity;
private String description;
//Setter/Getter
}
预订创建服务。
@Service
public class BookingService{
@Transactional
public Booking addBooking(final BookingDTO bookingRequest) {
LOG.debug("Creating new booking for request: {}", bookingRequest);
validateBookingData(bookingRequest);
return bookingCreateService.createBooking(bookingRequest);
}
}
@Service
public class BookingCreateService {
@Autowired
private BookingRepository bookingRepository;
@Autowired
private TableRepository tableRepository;
public Booking createBooking(final BookingDTO bookingRequest) {
Booking booking = null;
final LocalDateTime bookingStart = bookingRequest.getBookingTime();
final LocalDateTime bookingEnd = bookingRequest.getBookingTime().plusHours(1);
RestaurantTable table = tableRepository
.findAvailableTableWithAdequateSeatingCapacity(bookingStart, bookingEnd, bookingRequest.getCustomers())
.stream().findFirst().orElse(null);
if (table != null) {
booking = saveBooking(table, bookingStart, bookingEnd, bookingRequest.getCustomerName());
} else {
throwErrorWithRecomemdedTime(bookingRequest.getCustomers(), bookingStart);
}
return booking;
}
private Booking saveBooking(final RestaurantTable table, final LocalDateTime bookingStart,
final LocalDateTime bookingEnd, final String customerName) {
Booking booking = new Booking();
booking.setBookingStart(bookingStart);
booking.setBookingEnd(bookingEnd);
booking.setTable(table);
booking.setBookingId(RandomStringUtils.randomAlphanumeric(7));
booking.setCustomerName(customerName);
return bookingRepository.save(booking);
}
private void throwErrorWithRecomemdedTime(final Integer customerCount, final LocalDateTime bookingStart) {
Booking closestBookingWithFreeSlot = bookingRepository.findClosestBookingToInputTime(bookingStart);
StringBuilder errorMsg = new StringBuilder();
errorMsg.append("Table not available for capacity: ").append(customerCount).append(".");
if (closestBookingWithFreeSlot != null) {
errorMsg.append(" Table available after " + closestBookingWithFreeSlot.getBookingEnd() + ".");
}
throw new DataValidationException(errorMsg.toString());
}
}
如果我使用 Thread.sleep 保持 BookingService 的完成状态,并创建另一个预订同一张 table 的请求,那么它将在同一时间为同一张 table 创建两个预订。我怎样才能避免这种情况?我应该同步它吗?同步会导致性能问题吗?
最佳答案
如果您在数据库表上添加唯一约束(包括日期、表和时间段),只要您使用事务,您就应该在两者之一上收到错误。 您可以捕获错误并向客户端返回一条消息,表明时间不再可用。
关于java - 处理餐厅场景中的同时预订请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47428790/