Dominic Fuchs
Dominic Fuchs

Reputation: 315

JPA Bidirectional OneToOne Not working

I try to build a bidirectional relationship. I am using Spring Boot 1.5.4.RELEASE with Spring Boot JPA to generate my repositories. I try to save two entities which are associated to each other, but it isnt working. I commented the test-statements which fails.

My Entites:

Driver:

@Entity
@ToString
@EqualsAndHashCode
public class Driver {

    public static final String COLUMN_CAR = "car";



    @Id
    @GeneratedValue
    private long id;

    @Getter
    @Setter
    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = COLUMN_CAR)
    private Car car;

}

Car:

@Entity
@ToString
@EqualsAndHashCode
public class Car {

    @Id
    @GeneratedValue
    private long id;

    @Getter
    @Setter
    @OneToOne(mappedBy = Driver.COLUMN_CAR)
    private Driver driver;

}

I used Spring JPA to generate repositories.

DriverRepository:

@Repository
public interface DriverRepository extends CrudRepository<Driver, Long> { }

CarRepository:

@Repository
public interface CarRepository extends CrudRepository<Car, Long> { }

Test:

@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional
public class StackoverflowTest {

    @Autowired
    private DriverRepository driverRepository;

    @Autowired
    private CarRepository carRepository;

    @Test
    public void test1() {
        Driver driver = driverRepository.save(new Driver());
        Car car = carRepository.save(new Car());

        driver.setCar(car);

        driverRepository.save(driver);

        /* Success, so the driver got the car */
        driverRepository.findAll().forEach(eachDriver -> Assert.assertNotNull(eachDriver.getCar()));

        /* Fails, so the car doesnt got the driver */
        carRepository.findAll().forEach(eachCar -> Assert.assertNotNull(eachCar.getDriver()));
    }

    @Test
    public void test2() {
        Driver driver = driverRepository.save(new Driver());
        Car car = carRepository.save(new Car());

        car.setDriver(driver);

        carRepository.save(car);

        /* Success, so the car got the driver */
        carRepository.findAll().forEach(eachCar -> Assert.assertNotNull(eachCar.getDriver()));

        /* Fails, so the driver doesnt got the car */
        driverRepository.findAll().forEach(eachDriver -> Assert.assertNotNull(eachDriver.getCar()));
    }

}

In both tests the last statement fails. Any ideas? Thanks in Advice.

Upvotes: 0

Views: 894

Answers (1)

JB Nizet
JB Nizet

Reputation: 691775

Several mistakes in what you posted.

First:

@OneToOne(mappedBy = Driver.COLUMN_CAR)

mappedBy expects the name of the Java field/property on the other side of the association. Not the name of the database column. It works here because both happen to have the same name.

Second:

carRepository.findAll().forEach(eachCar -> Assert.assertNotNull(eachCar.getDriver()));

That fails simply because you're doing everything in a single transaction, and you failed to properly initialize the two sides of the association. So car.driver is just as you initialized it: null.

Third:

driverRepository.findAll().forEach(eachDriver -> Assert.assertNotNull(eachDriver.getCar()));

You made the same mistake as before, but worse. Here, you only initialized one side of the association, but you initialized the inverse side of the association (the one which has the mappedBy attribute). So the association won't even be saved in the database, as it would have been in your previous snippet.

Upvotes: 1

Related Questions