0

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.

Dominic Fuchs
  • 315
  • 1
  • 3
  • 10
  • Can you post the code where you create/get both ``User`` and ``UserBan``, how you persist it and how you fetch it back from the DB ? – Jan B. Jul 26 '17 at 16:15
  • I changed my entities, posted my repository-classes and my unit tests. :) hope you can help my out. – Dominic Fuchs Jul 27 '17 at 22:36

1 Answers1

1

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.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • So the first thing was not the problem. I dont understand why. I got Cascading enabled, so if I save them to db, I got the initialized object back from it. So why is it null? Again. The cascading and saving to db should solve the problem? Maybe I got some big issues in understanding how the association and the cascading works. Could you post me a snipped that does save my problem? So I can see my mistake? :) Would be awesome. – Dominic Fuchs Aug 10 '17 at 11:14
  • Regarding the first thing, read again. I said: *it works here because both happen to have the same name*. So it works only because the field and the column have the same name. What is expected is still a filed name, not a column name. The problem is that you think that *if I save them to db, I got the initialized object back from it*. That's incorrect. If you save something, JPA stores it, as is, in its persistence context (aka first-level cache). – JB Nizet Aug 10 '17 at 11:47