簡體   English   中英

Spring JPA 共享主鍵導致 org.hibernate.AssertionFailure: null identifier

[英]Spring JPA Shared primary key causes org.hibernate.AssertionFailure: null identifier

我正在使用 MySQL 數據庫制作一個 Spring Boot 應用程序,並且我正在嘗試設置類似這個示例的內容(簡化了問題) 在此處輸入圖片說明 其中一些可選實體可以保存有關用戶的額外數據。

這是我設置的簡化示例:Person.java:

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;

@Entity
public class Person {

    @Id
    @Column
    @GeneratedValue
    private Long id;

    @Column
    private String name;

    @OneToOne(cascade = CascadeType.ALL, mappedBy = "person", optional = true)
    @PrimaryKeyJoinColumn
    private Car car;

    //getters, setters and constructors
    public Person() {
        super();
    }
    public Person(Long id, String name) {
        super();
        this.id = id;
        this.name = name;
    }
    public Person(Long id, String name, Car car) {
        super();
        this.id = id;
        this.name = name;
        this.car = car;
    }
    public Long getId() { return id; }
    public String getName() { return name; }
    public Car getCar() { return car; }
    public void setCar(Car car) { this.car = car; }
    public void setId(Long id) { this.id = id; }
    public void setName(String name) { this.name = name; }
}

汽車.java:

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.MapsId;
import javax.persistence.OneToOne;

@Entity
public class Car {
    @Id
    @Column
    private Long id;
    
    @MapsId
    @OneToOne //NOTE A
    @JoinColumn(name ="id")
    private Person person;

    @Column
    private String brand;

    //Getters, setters and constructors
    public Car() {
        super();
    }
    public Car(Long id, Person person, String brand) { 
        super();
        this.id = id;
        this.person = person;
        this.brand = brand;
    }
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    public Person getPerson() { return person; }
    public void setPerson(Person person) { this.person = person; }
    public String getBrand() { return brand; }
    public void setBrand(String brand) { this.brand = brand; }

}

還有我的測試課:

@SpringBootTest
class BasicOneToOneTest  {

    @Autowired
    PersonRepo persons;
    @Autowired
    CarRepo cars;

    @Test
    void test() {
        Person dave = new Person(null, "Dave");
        persons.save(dave);
    
        Car car = new Car(dave.getId(), dave, "HAS_WHEELS");
        cars.save(car);

        dave = persons.findById(dave.getId()).get();
        assertEquals(true,  dave.getCar() != null );
    
        cars.delete(car);
    
        dave = persons.findById(dave.getId()).orElseGet(()->null);
        assertEquals(true,  dave!=null ); //NOTE B
    }

}

當按原樣運行時,我得到org.hibernate.AssertionFailure: null identifier如果我將 @OneToOne (在note A )更改為包含cascade = CascadeType.ALL則空標識符消失,但該人也被刪除。 (在注 B 處測試)

感謝您的幫助,謝謝:)

找到了一個解決方案,我發現運行測試如下有效:

@Test
void test() {
    Person dave = new Person(null, "Dave");
    persons.save(dave);
    
    Car car = new Car(dave.getId(), dave, "HAS_WHEELS");
    dave.setCar(car); //car is set into the parent entity
    persons.save(dave); //person is saved instead of the car
    
    
    dave = persons.findById(dave.getId()).get(); 
    assertEquals(true,  dave.getCar() != null );
    
    cars.delete(car);
    
    dave = persons.findById(dave.getId()).orElseGet(()->null); //skip?
    assertEquals(true,  dave!=null );
}

編輯:此處未按預期刪除汽車

編輯:更改@OneToOne 以使用MERGE而不是ALL似乎有效

    @OneToOne(cascade = CascadeType.MERGE, mappedBy = "person", optional = true)
    @PrimaryKeyJoinColumn
    private Car car;

這是我更改后使用的測試:

@Test
    void test2() {
        Person dave = new Person(null, "Dave");
        persons.save(dave);
        
        Car car = new Car(dave.getId(), dave, "HAS_WHEELS");
        
        dave.setCar(car);
        persons.save(dave);
        
        dave = persons.findById(dave.getId()).get(); 
        assertEquals(true,  dave.getCar() != null , "Dave does not have car assigned");
        
        cars.delete(car);
        
        
        dave = persons.findById(dave.getId()).orElseGet(()->null);
        assertEquals(true,  dave!=null, "Dave deleted" );
        
        assertEquals( false ,  cars.existsById(car.getId()), "Car not deleted" );
    }

如果有人有更好的解決方案,我仍然會感興趣。 但這暫時有效。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM