我有一个 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。但是当我在引擎表中有 @JoinColumn 来拥有 car_id 时,值变为 NULL。
答案 0 :(得分:0)
在您的一对一关系中,Engine
实体是关系的所有者,因为 engine
表具有 car_id
属性,而 car
表没有t 有 engine_id
属性。因此,Engine
实体是关系的所有者。
您必须将 @JoinColumn
注释放在 Car
类的 Engine
属性中,并将 @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
表的外键。从 car_id
表中删除 engine
列。您还必须重新映射实体,将 Engine
的 Car
属性映射到 @JoinColumn
并将其从 Engine
实体中删除,因此 Car
实体将是关系的所有者。这样,您可以保存 Car
实体,同时也会保存 Engine
实体。
答案 1 :(得分:0)
复制您的示例 as follows,在保存和检索带有关联的新创建引擎的新创建汽车时,我没有遇到任何问题(即使没有像 @JMSilla 建议的那样明确保存引擎)。
即使 engine
是关系的拥有方,(非拥有)persist
的 save
期间的 car
操作级联到 (拥有)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