2017-07-26 108 views
0

我試圖建立一個雙向關係。我使用Spring Boot 1.5.4.RELEASE和Spring Boot JPA來生成我的倉庫。我嘗試保存兩個相互關聯的實體,但它不起作用。我評論了那些失敗的測試報告。JPA雙向OneToOne不工作

我的entites:

司機:

@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; 

} 

汽車:

@Entity 
@ToString 
@EqualsAndHashCode 
public class Car { 

    @Id 
    @GeneratedValue 
    private long id; 

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

} 

我使用過Spring JPA生成庫。

DriverRepository:

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

CarRepository:

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

測試:

@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())); 
    } 

} 

在兩個測試中的最後一條語句失敗。有任何想法嗎?感謝您的建議。

+0

你可以發佈你創建/獲取User和UserBan的代碼嗎?你如何保存它以及如何從數據庫中獲取? – Matt

+0

我改變了我的實體,發佈了我的存儲庫類和我的單元測試。 :)希望你能幫助我出去。 –

回答

0

您發佈的內容有幾處錯誤。

第一:

@OneToOne(mappedBy = Driver.COLUMN_CAR) 

mappedBy預計在關聯的另一側Java字段/屬性的名稱。不是數據庫列的名稱。它在這裏工作,因爲它們碰巧具有相同的名稱。

二:

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

失敗只是因爲你正在做在一個事務中的一切,你無法正確初始化關聯的兩個方面。因此car.driver就像您初始化它:null。

三:

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

你像以前那樣犯同樣的錯誤,但糟糕的。在這裏,您只初始化關聯的一側,但初始化關聯(具有mappedBy屬性的關聯)的反向一側。因此,該關聯甚至不會保存在數據庫中,因爲它將在您之前的片段中。

+0

所以首先不是問題。 我不明白爲什麼。我啓用了Cascading,因此如果我將它們保存到數據庫中,我會從中獲取已初始化的對象。那爲什麼它是空的? 再次。級聯和保存到數據庫應該解決這個問題?也許我在理解協會和級聯如何工作方面遇到了一些重大問題。 你可以貼我一個剪切,確實保存我的問題嗎?所以我可以看到我的錯誤? :)會很棒。 –

+0

關於第一件事,請再閱讀一次。我說:*它在這裏工作,因爲它們碰巧具有相同的名稱*。所以它只能工作,因爲字段和列具有相同的名稱。預期的仍然是一個提交的名稱,而不是列名。問題是你認爲*如果我將它們保存到數據庫,我從它得到初始化的對象*。這是不正確的。如果您保存了某些內容,則JPA會將其保存在持久性上下文中(也稱爲第一級緩存)。 –