![](/img/trans.png)
[英]update @OneToMany relationship (Spring Boot, Spring Data)
[英]How to update entity with OneToMany relationship in Spring Boot
我是 Spring 引导的新手,我正在编写一个应用程序来练习,使用 Postresql 作为数据库。 该应用程序是关于航空的。 有 4 个实体:Airline、Airplane、Airport 和 Flight。
我尝试了 GET、POST 和 DELETE 请求,所有这些都适用于航空公司、飞机和机场,但我在尝试添加和更新航班时遇到了问题。 Flight 有 4 个 ManyToOne 关系,这是 class:
@Entity
@Table
public class Flight {
@Id
@Column(name = "flight_number")
private String flightNumber;
@ManyToOne
@JoinColumn(name = "origin")
private Airport origin;
@ManyToOne
@JoinColumn(name = "destination")
private Airport destination;
@Column(name = "departure_time")
private Timestamp departureTime;
@Column(name = "arrival_time")
private Timestamp arrivalTime;
@ManyToOne
@JoinColumn(name = "airline")
private Airline airline;
@ManyToOne
@JoinColumn(name = "airplane")
private Airplane airplane;
private Time duration;
private int passengers;
...
}
我不明白的是如何插入和更新这个实体而不需要传递Objects
( Airline
和Airport
)而只传递外键(就像直接在数据库上工作时一样)。
这是我添加需要对象的新航班的代码:
public void addFlight(Flight flight) {
boolean exists = flightRepository.existsById(flight.getFlightNumber());
if (exists) {
throw new IllegalStateException("Flight with number" + flight.getFlightNumber()
+ "already exists");
}
flightRepository.save(flight);
}
我还尝试为存储库中的更新编写一个特定的查询,然后调用 PUT 请求,但我收到一些错误提示我需要传递 Airline 和 Airport,而不是表示这两个实体 ID 的字符串。
*@Modifying
@Query("update Flight " +
"set origin = :origin, " +
"destination = :destination, " +
"departureTime = :departureTime, " +
"arrivalTime = :arrivalTime, " +
"airline = :airline, " +
"airplane = :airplane, " +
"passengers = :passengers, " +
"duration = :duration " +
"where flightNumber = :flightNumber")
void updateFlight(@Param("flightNumber") String flightNumber,
@Param("origin") String origin,
@Param("destination") String destination,
@Param("departureTime") Timestamp departureTime,
@Param("arrivalTime") Timestamp arrivalTime,
@Param("airline") String airline,
@Param("airplane") Long airplane,
@Param("passengers") Integer passengers,
@Param("duration") Time duration);*/
总结一下:我想知道是否有一种方法可以避免在创建和更新过程中传递表示 ManyToOne 关系的整个 Object。
方法addFlight(Flight flight)
是从您的 controller 调用的吗? 如果是这种情况,您应该从您的 controller 获得一个DTO ,您将在服务层的实体中获得 map。
在 DTO 中,您需要提供Airline
、 Airplane
和Airport
对象的 ID,以便您可以从数据库中检索它们并将它们设置在Flight
实体上。
这是我可以建议的解决方案:
void addFlight (FlightRequest flightRequest) {
boolean exists = flightRepository.existsById(flightRequest.flightNumber());
if (exists) {
throw new IllegalStateException("Flight with number" + flight.getFlightNumber()
+ "already exists");
}
Flight flight = new Flight();
airportRepository.findById(flightRequest.airportOriginId())
.ifPresentOrElse(airportOrigin -> {
flight.setAirportOrigin(airportOrigin);
},
() -> new IllegalStateException(...)
);
airportRepository.findById(flightRequest.airportDestinationId())
.ifPresentOrElse(airportDestination -> {
flight.setAirportDestination(airportDestination);
},
() -> new IllegalStateException(...)
);
airlineRepository.findById(flightRequest.airlineId())
.ifPresentOrElse(airline -> {
flight.setAirline(airline);
},
() -> new IllegalStateException(...)
);
airplaneRepository.findById(flightRequest.airplaneId())
.ifPresentOrElse(airplane -> {
flight.setAirplane(airplane);
},
() -> new IllegalStateException(...)
);
flight.setFlightNumber(flightRequest.flightNumber());
flight.setDepartureTime(flightRequest.departureTime());
flight.setArrivalTime(flightRequest.arrivalTime());
flight.setDuration(flightRequest.duration());
flight.setPassengers(flightRequest.passengers());
...
flightRepository.save(flight);
}
public record FlightRequest(
String flightNumber,
String airportOriginId,
String airportDestinationId,
Timestamp departureTime,
Timestamp arrivalTime,
String airlineId,
String airplaneId,
Time duration,
int passengers,
...
) {
}
为了更新您的Flight
,您可以这样做:
Flight updateFlight (FlightRequest flightRequest) {
Flight flight = flightRepository.findById(flightRequest.flightNumber())
.orElseThrow(...);
// Same as above without the call for existsById
...
}
如果你想进一步了解 go,自 Spring 版本 2.7 数据 JPA 以来,你可以使用getReferenceById
方法而不是findById
。 在那种情况下 Spring 数据 JPA 不会生成 SQL 语句来获取实体,在我们的例子中我们只想设置外键。 你可以在这里找到更多相关信息
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.