我正在创建一个简单的春季应用程序,它应该在研讨会上预订座位。让我们说Booking
类看起来像这样
@Entity
@Table(name = "bookings")
@IdClass(BookingId.class)
public class Booking{
@Id
private Long seminarId;
@Id
private String seatNo;
// .. other fields like perticipant info
// .. getter setters
}
当然是BookingId
类:
public class BookingId implements Serializable{
private static final long serialVersionUID = 1L;
private Long seminarId;
private String seatNo;
// .. constructors, getters, setters
}
我有repository
@Repository
public interface BookingsRepository extends JpaRepository<Booking, BookingId>{
}
当预订请求到达时,在控制器中我首先检查是否已经存在具有相同的seminer id和座位号的预订,如果它不存在我创建一个
@RequestMapping(method = RequestMethod.POST)
public ResponseEntity<BaseCrudResponse> createNewBooking(@Valid @RequestBody NewBookingDao newBookingDao, BindingResult bindingResult){
logger.debug("Request for a new booking");
// .. some other stuffs
Booking newBooking = new Booking();
newBooking.setSeminarId(newBookingDao.getSeminarId());
newBooking.setSeatNumber(newBookingDao.getSeatNumber());
// .. set other fields
Booking existing = bookingsRepository.findOne(new BookingId(newBooking.getSeminarId(), newBooking.getSeatNumber());
if (existing == null)
bookingsRepository.save(newBooking);
return new ResponseEntity<>(new BaseCrudResponse(0), HttpStatus.CREATED);
}
return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST);
}
现在如果save
的{{1}}方法没有完成提交事务而另一个请求已经超过存在检查会发生什么?可能有不正确的预订(最后一次提交将覆盖之前的提交)。这种情况可能会发生吗?存储库是否会确保它在另一次保存调用之前完成事务?
还有什么方法可以告诉Jpa抛出一些异常(对于IntegrityConstraintException,如果复合键(在本例中为seminerId和seatNumber)已经存在?现在在当前设置中它只是更新行。
答案 0 :(得分:1)
您可以使用javax.persistence.LockModeType.PESSIMISTIC_WRITE,因此除了获得锁定的事务之外的其他事务无法更新实体。
如果您使用spring-data&gt; 1.6您可以使用@Lock注释存储库方法:
interface BookingsRepository extends Repository<Booking, Long> {
@Lock(LockModeType.PESSIMISTIC_WRITE)
Booking findOne(Long id);
}
当然,您需要处理控制器中可能出现的锁定异常。