使用复合键时出现 JpaSystemException

JpaSystemException when using composite key

我正在构建一个 spring 引导应用程序,但我遇到了 JpaSystemException: attempted to assign id from null one-to-one property 错误。让我给你一些关于这个项目的细节。

首先,我有以下数据库模式

describe airports;

+--------------------------+------------+------+-----+---------+-------+
| Field                    | Type       | Null | Key | Default | Extra |
+--------------------------+------------+------+-----+---------+-------+
| airport_id               | int(11)    | NO   | PRI | NULL    |       |
| airport_name             | text       | NO   |     | NULL    |       |
+--------------------------+------------+------+-----+---------+-------+

describe flights;

+------------------------+---------+------+-----+---------+-------+
| Field                  | Type    | Null | Key | Default | Extra |
+------------------------+---------+------+-----+---------+-------+
| flight_from_airport_id | int(11) | NO   | PRI | NULL    |       |
| flight_to_airport_id   | int(11) | NO   | PRI | NULL    |       |
| flight_type            | int(11) | NO   | PRI | NULL    |       |
+------------------------+---------+------+-----+---------+-------+

基本上,table 航班用于存储从一个机场到另一个机场的航班数据。

我有两个实体;机场及航班如下:

Airport.java

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "airports")
public class Airport {
    @Id
    @Column(name="airport_id")
    private int airportId;
    
    @Column(name="airport_name")
    private String airportName;
    
    //Getters and Setters

    public Airport(int airportId, String airportName) {
        this.airportId = airportId;
        this.airportName = airportName;
    }
}

Flight.java

import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.MapsId;
import javax.persistence.Table;

@Entity
@Table(name = "flights")
public class Flight {
    
    @EmbeddedId
    FlightPrimaryKey flightPrimaryKey;

    @MapsId("fromAirport")
    @ManyToOne
    @JoinColumn(name = "flightFromAirportId")
    private Airport fromAirport;

    @MapsId("toAirport")
    @ManyToOne
    @JoinColumn(name = "flightToAirportId")
    private Airport toAirport;

    @Column(name="flight_type")
    private int flightType;

    //Getters and Setters

    public Flight(FlightPrimaryKey flightPrimaryKey, int flightType) {
        this.flightPrimaryKey = flightPrimaryKey;
        this.flightType = flightType;
    }
}

因为我想要 class 航班的组合键,所以我有一个 ID class。

FlightId.java


import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Embeddable;

@Embeddable
public class FlightId implements Serializable {
        
    @Column(name = "flight_from_airport_id")
    private int fromAirport;

    @Column(name = "flight_to_airport_id")
    private int toAirport;

    // Getters and Setters, hashcode, equals

    public TransferPrimaryKey(int fromAirport, int toAirport) {
        this.fromAirport = fromAirport;
        this.toAirport = toAirport;
    }
}

然后我有一个 JPA 存储库

FlightRepository.java

public interface FlightRepository extends JpaRepository<Flight, FlightId>{}

为了测试以上内容,我使用以下代码:

@ExtendWith(SpringExtension.class)
@SpringBootTest
public class FlightTest {

    @Autowired
    private AiportRepository airportRepository;

    @Autowired
    private FlightRepository flightRepository;

    @Test
    public void shouldStoreAFlight() {
        Airport fromAirport = airportRepository.save(new Airport(1, "LAX");
        Airport toAirport = airportRepository.save(new Airport(2, "JFK")
        FlightId flightId = new FlightId(fromAirport.getId(), toAirport.getId());
        Flight flight = flightRepository.save(new Flight(flightId, 1));
    }
}

当我运行上面的代码时,我得到了JpaSystemException。我也不明白为什么错误说一对一 属性。我只定义了一个多对一属性。显然我错过了一些东西。

解决方案应该是设置您的引用:

public void shouldStoreAFlight() {
  Airport fromAirport = airportRepository.save(new Airport(1, "LAX");
  Airport toAirport = airportRepository.save(new Airport(2, "JFK")
  FlightId flightId = new FlightId(fromAirport.getId(), toAirport.getId());
  Flight flight  = new Flight(flightId, 1);
  flight.setFromAirport(fromAirport);
  flight.setToAirport(toAirport);
  flight = flightRepository.save(flight);
}

应该不需要使用上面的代码设置 FlightId 中的值,但我保留它以匹配您的构造函数,并且因为您将它们设置为 int 而不是一个允许空值的整数。