我有兩個物體預訂和 travelAgentBooking,預訂可以單獨存在,而 travelAgentBooing 必須有一個預訂。
TABookingEntity 如下
@Entity
@ApplicationScoped
@Table(name = "TABooking")
@NamedQuery(name = "TABooking.findAll", query = "SELECT t FROM TABookingEntity t ORDER BY t.id ASC")
public class TABookingEntity {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "TABookingId_seq")
@SequenceGenerator(name = "TABookingId_seq", initialValue = 1, allocationSize = 1)
private Long id;
@OneToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "booking_id", nullable = false)
private BookingEntity flightbooking;
// belong to upstream booking so we just store id here
private Long taxibookingid;
private Long hotelbookingid;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public BookingEntity getFlightbooking() {
return flightbooking;
}
public void setFlightbooking(BookingEntity flightbooking) {
this.flightbooking = flightbooking;
if (flightbooking != null) {
flightbooking.setTravelAgentBooking(this);
}
}
public Long getTaxibookingId() {
return taxibookingid;
}
public void setTaxibookingId(Long taxibookingid) {
this.taxibookingid = taxibookingid;
}
public Long getHotelbookingId() {
return hotelbookingid;
}
public void setHotelbookingId(Long hotelbookingid) {
this.hotelbookingid = hotelbookingid;
}
BookingEntity 在下面
@Entity
@ApplicationScoped
@Table(name = "booking")
@NamedQueries({ @NamedQuery(name = "Booking.findAll", query = "SELECT b FROM BookingEntity b ORDER BY b.d ASC"),
@NamedQuery(name = "Booking.findByFlight", query = "SELECT b FROM BookingEntity b WHERE b.flight = :flight"),
@NamedQuery(name = "Booking.findByDate", query = "SELECT b FROM BookingEntity b WHERE b.d = :d") })
public class BookingEntity {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "bookingId_seq")
@SequenceGenerator(name = "bookingId_seq", initialValue = 1, allocationSize = 1)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "customer_id", nullable = false)
private CustomerEntity customer;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "flight_id", nullable = false)
private FlightEntity flight;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "travelAgentBooking_id", nullable = true)
private TABookingEntity travelAgentBooking;
@NotNull
@Column(name = "date")
private Date d;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public CustomerEntity getCustomer() {
return customer;
}
public void setCustomer(CustomerEntity customer) {
this.customer = customer;
if(customer != null)
customer.addBooking(this);
}
public FlightEntity getFlight() {
return flight;
}
public void setFlight(FlightEntity flight) {
this.flight = flight;
}
public Date getDate() {
return new Date(d.getTime());
}
public void setDate(Date d) {
this.d = d;
}
public TABookingEntity getTravelAgentBooking() {
return travelAgentBooking;
}
public void setTravelAgentBooking(TABookingEntity travelAgentBooking) {
this.travelAgentBooking = travelAgentBooking;
}
這是我首先創建預訂的代碼,然后將其設定為預訂。
然后我正在嘗試更新預訂,因為它在創建時沒有 travelAgentBooking 可以關聯。
Booking booking = flightService.createBooking(tabooking.getFlightbooking());
tabooking.setFlightbooking(booking);
,,,,,,,,,,,
,,,,,,,,,,,
tabookingService.create(tabooking);
flightService.updateBooking(tabooking.getFlightbooking().getId(), tabooking.getFlightbooking());
運行它之后,travelAgentBooking 的表就完美了。但是對于任何預訂物件,參考 travelAgentBooking 的預訂表列始終為空。
更新:
@PUT
@Path("/{id:[0-9] }")
@Operation(description = "Update a Booking in the database")
@APIResponses(value = { @APIResponse(responseCode = "200", description = "Booking updated successfully"),
@APIResponse(responseCode = "400", description = "Invalid Booking supplied in request body"),
@APIResponse(responseCode = "404", description = "Booking with id not found"),
@APIResponse(responseCode = "409", description = "Booking details supplied in request body conflict with another existing Booking"),
@APIResponse(responseCode = "500", description = "An unexpected error occurred whilst processing the request") })
@Transactional
public Response updateBooking(
@Parameter(description = "Id of Booking to be updated", required = true) @Schema(minimum = "0") @PathParam("id") Integer id,
@Parameter(description = "JSON representation of Booking object to be updated in the database", required = true) Booking booking) {
Customer customer = customerService.findById(booking.getCustomer().getId())
.orElseThrow(() -> new RestServiceException("We can't found customer", Response.Status.BAD_REQUEST));
if (!customer.equals(booking.getCustomer()))
throw new RestServiceException("use custoemr's own API for it update", Response.Status.BAD_REQUEST);
Flight flight = flightService.findById(booking.getFlight().getId())
.orElseThrow(() -> new RestServiceException("We can't found flight", Response.Status.BAD_REQUEST));
if (!flight.equals(booking.getFlight()))
throw new RestServiceException("use custoemr's own API for it update", Response.Status.BAD_REQUEST);
try {
bookingService.validateBooking(booking);
} catch (ConstraintViolationException ce) {
// Handle bean validation issues
Map<String, String> responseObj = new HashMap<>();
for (ConstraintViolation<?> violation : ce.getConstraintViolations()) {
responseObj.put(violation.getPropertyPath().toString(), violation.getMessage());
}
throw new RestServiceException("Bad Request", responseObj, Response.Status.BAD_REQUEST, ce);
} catch (UniqueFlightWithDateException e) {
// we are updating an existence flight, so ignore this as expected
}
try {
bookingService.update(id);
} catch (ServiceException e) {
Map<String, String> responseObj = new HashMap<>();
responseObj.put("id", "please ensure the id is associated with this number");
throw new RestServiceException("Bad Request", responseObj, Response.Status.NOT_FOUND, e);
}
bookingService.update(id);
return Response.ok(booking).build();
}
BookingEntity update(BookingEntity booking) {
log.info("BookingRepository.update() - Updating " booking.getId());
em.merge(booking);
return booking;
}
uj5u.com熱心網友回復:
從原始發布的代碼來看,問題在于您有兩個非常獨立的單向關系并且只設定其中一個。由于它們是獨立的,因此另一個保持為 null 并且在設定之前不能為 null 以外的任何內容。
@OneToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "booking_id", nullable = false)
private BookingEntity flightbooking;
連接列在“TABooking”表中設定一個外鍵以指向 bookingEntity。它要求設定此關系參考以填充該外鍵值。同樣的事情:
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "travelAgentBooking_id", nullable = true)
private TABookingEntity travelAgentBooking
它在“booking”表中創建自己的 travelAgentBooking_id 外鍵列,在您更新預訂實體并設定此參考之前,該列將保持為空。如果只設定一側,另一側將始終在資料庫中保持為空。
但是模型和您的期望存在兩個問題。首先,從評論中,您不打算這是兩個獨立的關系,而是希望它是一個雙向關系。為此,您需要一個外鍵,并選擇“擁有”它的一方。擁有它的一方控制它:
@OneToOne(mappedBy "flightbooking", fetch = FetchType.LAZY)
private TABookingEntity travelAgentBooking
使用 mappedBy 告訴 JPA 另一方擁有該關系。只有當您設定 TABookingEntity.flightbooking 參考并保存/合并 TABookingEntity 實體時,才會設定外鍵列。
其次是您使用 JSON 等 Json 序列化并假設它遵守您的物件模型和 JPA 映射。它不是。JPA 注釋是為了讓您的持久性提供者告訴它如何將您的模型序列化/反序列化到資料庫中,但對于 JSON 序列化(或 xml 或任何其他 REST 格式)沒有任何意義。您需要告訴您的 JSON 工具如何處理您的關系,這完全取決于您將如何期待和發送 JSON。有許多教程和不同的策略可以解決這個問題(請參閱此鏈接以獲得良好的入門知識),但最簡單的方法通常是選擇圖表的一部分并使用 @JsonIgnore 排除它們:
@OneToOne(mappedBy "flightbooking", fetch = FetchType.LAZY)
@JsonIgnore
private TABookingEntity travelAgentBooking
這意味著您收到的代表預訂的任何 JSON 都將具有 null tr??avelAgentBooking。因此,如果您需要查看或設定這種關系,您的 api 將不得不發送/接收 TABookingEntity,它仍然會序列化航班預訂參考。我選擇這種方式是因為 flightbooking 擁有這種關系,所以它與 JPA 匹配,但它不需要。您可以而且應該弄清楚什么適用于您的客戶端應用程式,它可能與 JPA 映射不同。我希望預訂總是需要知道 TABookingEntity 并且您希望將其發送給客戶端,因此您可以將 @JsonIgnore 注釋放在另一邊。如果你這樣做了,你只需要確保當你想要更改或添加 TABookingEntity 時,你適當地修復了 TABookingEntity.flightbooking 參考,這樣你就不會'
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/531576.html
標籤:爪哇jpa
