You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot中如何通过外键而非关联对象增改Flight实体

解决方案

一、新增Flight(仅传外键ID)

不需要传入完整的关联实体对象,只需通过ID获取关联实体的懒加载代理对象即可(Spring Data JPA的getReferenceById方法不会触发实际数据库查询,仅返回代理,性能更优),再将其设置到Flight实体中保存。

示例代码:

Service层修改:

@Service
@Transactional
public class FlightService {
    private final FlightRepository flightRepository;
    private final AirportRepository airportRepository;
    private final AirlineRepository airlineRepository;
    private final AirplaneRepository airplaneRepository;

    // 构造注入依赖
    public FlightService(FlightRepository flightRepository, AirportRepository airportRepository, AirlineRepository airlineRepository, AirplaneRepository airplaneRepository) {
        this.flightRepository = flightRepository;
        this.airportRepository = airportRepository;
        this.airlineRepository = airlineRepository;
        this.airplaneRepository = airplaneRepository;
    }

    public void addFlight(String flightNumber, String originId, String destinationId, String airlineId, Long airplaneId, Timestamp departureTime, Timestamp arrivalTime, Time duration, int passengers) {
        if (flightRepository.existsById(flightNumber)) {
            throw new IllegalStateException("Flight with number " + flightNumber + " already exists");
        }

        // 通过ID获取关联实体的代理对象(不查询完整数据)
        Airport origin = airportRepository.getReferenceById(originId);
        Airport destination = airportRepository.getReferenceById(destinationId);
        Airline airline = airlineRepository.getReferenceById(airlineId);
        Airplane airplane = airplaneRepository.getReferenceById(airplaneId);

        // 构建Flight实体并保存
        Flight flight = new Flight();
        flight.setFlightNumber(flightNumber);
        flight.setOrigin(origin);
        flight.setDestination(destination);
        flight.setAirline(airline);
        flight.setAirplane(airplane);
        flight.setDepartureTime(departureTime);
        flight.setArrivalTime(arrivalTime);
        flight.setDuration(duration);
        flight.setPassengers(passengers);

        flightRepository.save(flight);
    }
}

二、更新Flight(仅传外键ID)

你之前的自定义JPQL报错是因为直接用ID赋值给实体类型字段不符合JPQL语法,需修改语句,通过关联实体的ID属性来关联外键,同时确保方法添加事务和修改注解。

示例代码:

Repository层修改:

@Repository
public interface FlightRepository extends JpaRepository<Flight, String> {

    @Modifying
    @Transactional
    @Query("update Flight f " +
            "set f.origin.id = :originId, " +
            "f.destination.id = :destinationId, " +
            "f.departureTime = :departureTime, " +
            "f.arrivalTime = :arrivalTime, " +
            "f.airline.id = :airlineId, " +
            "f.airplane.id = :airplaneId, " +
            "f.passengers = :passengers, " +
            "f.duration = :duration " +
            "where f.flightNumber = :flightNumber")
    void updateFlight(@Param("flightNumber") String flightNumber,
                      @Param("originId") String originId,
                      @Param("destinationId") String destinationId,
                      @Param("departureTime") Timestamp departureTime,
                      @Param("arrivalTime") Timestamp arrivalTime,
                      @Param("airlineId") String airlineId,
                      @Param("airplaneId") Long airplaneId,
                      @Param("passengers") Integer passengers,
                      @Param("duration") Time duration);
}

说明:

  • JPQL中通过f.origin.id直接关联外键字段,允许传入ID字符串/数值,无需完整实体对象。
  • @Modifying标记这是修改操作,@Transactional确保操作在事务上下文执行。

三、进阶:使用DTO接收参数

为了更规范地处理前端传入的参数,可定义DTO类封装所有字段(含外键ID),再在Service层将DTO转换为Flight实体:

FlightDTO示例:

public class FlightDTO {
    private String flightNumber;
    private String originId;
    private String destinationId;
    private Timestamp departureTime;
    private Timestamp arrivalTime;
    private String airlineId;
    private Long airplaneId;
    private Time duration;
    private int passengers;

    // Getters and Setters
}

Service层使用DTO:

public void addFlight(FlightDTO flightDTO) {
    if (flightRepository.existsById(flightDTO.getFlightNumber())) {
        throw new IllegalStateException("Flight with number " + flightDTO.getFlightNumber() + " already exists");
    }

    Airport origin = airportRepository.getReferenceById(flightDTO.getOriginId());
    Airport destination = airportRepository.getReferenceById(flightDTO.getDestinationId());
    Airline airline = airlineRepository.getReferenceById(flightDTO.getAirlineId());
    Airplane airplane = airplaneRepository.getReferenceById(flightDTO.getAirplaneId());

    Flight flight = new Flight();
    BeanUtils.copyProperties(flightDTO, flight); // 复制非关联字段
    flight.setOrigin(origin);
    flight.setDestination(destination);
    flight.setAirline(airline);
    flight.setAirplane(airplane);

    flightRepository.save(flight);
}

内容的提问来源于stack exchange,提问作者Raul

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 14:55:20