I am building a spring boot application and I am stuck with the JpaSystemException: attempted to assign id from null one-to-one property
error. Let me give you some details about the project.
First of all, I have the following db schema
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 | |
------------------------ --------- ------ ----- --------- -------
Basically, table flights is used to store data for flights from one airport to another.
I have two entities; airport and flight as follows:
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;
}
}
Because I want a composite key for the class Flight, I have an 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;
}
}
Then I have a JPA repository
FlightRepository.java
public interface FlightRepository extends JpaRepository<Flight, FlightId>{}
And to test the above I use the following code:
@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));
}
}
When I run the above code, I get the JpaSystemException. I also cannot understand why the error says about one-to-one property. I have only defined a many-to-one property. Clearly I am missing something.
CodePudding user response:
Solution should be to set your references:
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);
}
There should be no need to set the values in FlightId with the above code, but I left it to match your constructors, and because you have them set to int instead of an Integer that allows nulls.