【问题标题】:JPA OneToOne not Updating Foreign KeyJPA OneToOne 不更新外键
【发布时间】:2021-08-16 01:44:03
【问题描述】:

我在 Java 中有一个具有 @Id 列的类。这是 CAR 的主键:

@Entity
@Table(name = "car")
public class CarDomain {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(nullable = false)
    private UUID id;

    @OneToOne(cascade = CascadeType.ALL, mappedBy = "car")
    private EngineDomain engine;
    
}

在 Engine 类中,我有一个主键(引擎的 ID)和一个外键 car_id 来引用引擎所属的 CAR 的 ID:

@Entity
public class EngineDomain {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(nullable = false)
    private UUID id;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "car_id", referencedColumnName = "id")
    private CarDomain car;
    
}

在我的 PostgresDB 中,Engine 表正在加载所有值为 NULL 的 car_id 列。

在表 CAR 中插入 engine_id ForeignKey,所有值都正确加载。汽车所属的engine_id。但是,当我在 Engine 表中有 @JoinColumn 来获得 car_id 时,值会变为 NULL。

【问题讨论】:

    标签: java jpa spring-data-jpa data-annotations spring-annotations


    【解决方案1】:

    在您的一对一关系中,Engine 实体是关系的所有者,因为engine 表具有car_id 属性,而car 表没有engine_id 属性。因此,Engine 实体是关系的所有者。

    您必须将@JoinColumn 注释放在Engine 类的Car 属性中,并将@OneToOne 注释与属性cascade = CascadeType.ALL 放在一起。 Car 实体是关系的另一方,但它不是它的所有者,因此您必须将 @OneToOne 注释与 mappedBy = "car" 属性放在一起。

    如果您在保存实体时还希望保存另一方,则必须保留 Engine 对象,因为它是所有者:

    Engine engine = new Engine();
    Car car = new Car();
    
    engine.setCar(car);
    
    entityManager.persist(engine);
    

    如果您持久化car 对象而不是engine,则不会持久化engine 对象:

    Engine engine = new Engine();
    Car car = new Car();
    
    car.setEngine(engine);
    
    entityManager.persist(car);
    

    如果您想反转此行为,请更改 car 表,在其中添加 engine_id 列和 engine 表的外键。从engine 表中删除car_id 列。您还必须重新映射实体,将CarEngine 属性映射到@JoinColumn 并将其从Engine 实体中删除,因此Car 实体将成为关系的所有者。这样就可以保存Car实体,同时Engine实体也会被保存。

    【讨论】:

    • 你好 JMSilla。不好意思推迟了。我在周五根据您的指示进行了适当的更正。问题出在我坚持对象的顺序上。成功了!非常感谢!
    【解决方案2】:

    复制您的示例as follows,我在保存和检索具有关联的新创建引擎的新创建汽车时没有遇到任何问题(即使没有明确保存引擎,正如@JMSilla 建议的那样)。

    尽管engine 是关系的拥有方,但(非拥有)save 期间的persist 操作会级联到(拥有)engine(由于CascadeType.ALL)。

    但是,这仅在关联正确同步(设置了相互引用)时才有效:

        car.setEngine(engine); // <-- save(car) will cascade persist to engine
        engine.setCar(car); // <-- saving the engine will also persist the foreign key of the associated car
    
        repository.save(car); // both entities and their association are persisted
    

    【讨论】:

    • 你好,弗拉迪米尔。成功了!非常感谢!祝您度过愉快的一周。
    • 不客气!随意将答案标记为“已接受”或投票以防它有助于解决问题
    猜你喜欢
    • 1970-01-01
    • 2016-05-26
    • 1970-01-01
    • 2020-10-10
    • 1970-01-01
    • 1970-01-01
    • 2019-04-16
    • 2020-07-08
    • 1970-01-01
    相关资源
    最近更新 更多