我想使用Spring Data JDBC和PostgreSQL对一对一关系进行建模,但是我无法以正确的方式设置根聚合。
存在以下情况:Picture,SQL
每个引擎都是唯一的,car
具有唯一的列engine_id
,列是engine.id
的外键,truck
也是如此。因此,汽车和卡车应该是根集合,因此,当汽车或卡车被删除时,引擎表中的引用行也应被删除。
根据我对Spring Data JDBC Aggregates的理解
如果多个集合引用同一实体,则该实体不能成为引用该实体的那些集合的一部分,因为它只能是一个集合的一部分。
所以问题是:
car
和truck
执行CRUD操作,更改也将反映到engine
?这是我的看法,不起作用,但应阐明我要完成的工作。
Car.java
package com.example.dao.model;
import org.springframework.data.annotation.Id;
import org.springframework.data.domain.Persistable;
import org.springframework.data.relational.core.mapping.Column;
import org.springframework.data.relational.core.mapping.Table;
import java.util.UUID;
@Table("car")
public class Car implements Persistable<UUID> {
@Id
private UUID id;
String brand;
String model;
@Column("engine_id")
Engine engine;
public void setId(UUID id) {
this.id = id;
}
@Override
public UUID getId() {
return id;
}
@Override
public boolean isNew() {
return id == null;
}
}
Engine.java
package com.example.dao.model;
import org.springframework.data.annotation.Id;
import org.springframework.data.domain.Persistable;
import org.springframework.data.relational.core.mapping.Table;
import java.time.LocalDateTime;
import java.util.UUID;
@Table("engine")
public class Engine implements Persistable<UUID> {
@Id
private UUID id;
String name;
LocalDateTime dateCreated;
String type;
public void setId(UUID id) {
this.id = id;
}
@Override
public UUID getId() {
return id;
}
@Override
public boolean isNew() {
return id == null;
}
}
Truck.java
package com.example.dao.model;
import org.springframework.data.annotation.Id;
import org.springframework.data.domain.Persistable;
import org.springframework.data.relational.core.mapping.Column;
import org.springframework.data.relational.core.mapping.Table;
import java.util.UUID;
@Table("truck")
public class Truck implements Persistable<UUID> {
@Id
private UUID id;
String brand;
String model;
Integer cargoMaxWeight;
String truckType;
@Column("engine_id")
Engine engine;
public void setId(UUID id) {
this.id = id;
}
@Override
public UUID getId() {
return id;
}
@Override
public boolean isNew() {
return id == null;
}
}
答案 0 :(得分:1)
设法找到解决方案,问题是当数据库中的模型不同时,我无法理解从Car
引用Truck
和Engine
类的问题。 / p>
Car.java
package com.backend.dao.model;
import org.springframework.data.annotation.Id;
import org.springframework.data.domain.Persistable;
import java.util.Objects;
import java.util.UUID;
public class Car implements Persistable<UUID> {
@Id
private UUID id;
private String brand;
private String model;
public void setId(UUID id) {
this.id = id;
}
@Override
public UUID getId() {
return id;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
@Override
public boolean isNew() {
return id == null;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof Car)) {
return false;
}
Car car = (Car) o;
return Objects.equals(id, car.id) &&
Objects.equals(brand, car.brand) &&
Objects.equals(model, car.model);
}
@Override
public int hashCode() {
return Objects.hash(id, brand, model);
}
}
Truck.java
package com.backend.dao.model;
import org.springframework.data.annotation.Id;
import org.springframework.data.domain.Persistable;
import org.springframework.data.relational.core.mapping.Table;
import java.util.Objects;
import java.util.UUID;
@Table("truck")
public class Truck implements Persistable<UUID> {
@Id
private UUID id;
private String brand;
private String model;
private Integer cargoMaxWeight;
private String truckType;
public void setId(UUID id) {
this.id = id;
}
@Override
public UUID getId() {
return id;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public Integer getCargoMaxWeight() {
return cargoMaxWeight;
}
public void setCargoMaxWeight(Integer cargoMaxWeight) {
this.cargoMaxWeight = cargoMaxWeight;
}
public String getTruckType() {
return truckType;
}
public void setTruckType(String truckType) {
this.truckType = truckType;
}
@Override
public boolean isNew() {
return id == null;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof Truck)) {
return false;
}
Truck truck = (Truck) o;
return Objects.equals(id, truck.id) &&
Objects.equals(brand, truck.brand) &&
Objects.equals(model, truck.model) &&
Objects.equals(cargoMaxWeight, truck.cargoMaxWeight) &&
Objects.equals(truckType, truck.truckType);
}
@Override
public int hashCode() {
return Objects.hash(id, brand, model, cargoMaxWeight, truckType);
}
}
Engine.java
package com.backend.dao.model;
import org.springframework.data.annotation.Id;
import org.springframework.data.domain.Persistable;
import org.springframework.data.relational.core.mapping.Column;
import org.springframework.data.relational.core.mapping.Table;
import java.time.LocalDateTime;
import java.util.Objects;
import java.util.UUID;
@Table("engine")
public class Engine implements Persistable<UUID> {
@Id
private UUID id;
private String name;
private LocalDateTime dateCreated;
private String type;
@Column("engine_id")
private Car car;
@Column("engine_id")
private Truck truck;
public void setId(UUID id) {
this.id = id;
}
@Override
public UUID getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public LocalDateTime getDateCreated() {
return dateCreated;
}
public void setDateCreated(LocalDateTime dateCreated) {
this.dateCreated = dateCreated;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
@Override
public boolean isNew() {
return id == null;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof Engine)) {
return false;
}
Engine engine = (Engine) o;
return Objects.equals(id, engine.id) &&
Objects.equals(name, engine.name) &&
Objects.equals(dateCreated, engine.dateCreated) &&
Objects.equals(type, engine.type);
}
@Override
public int hashCode() {
return Objects.hash(id, name, dateCreated, type);
}
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
public Truck getTruck() {
return truck;
}
public void setTruck(Truck truck) {
this.truck = truck;
}
}
但是,该解决方案不符合要求-对Engine.java
执行的CRUD操作反映在Car.java
和Truck.java
上。而且我想实现在Car.java
上反映了在Truck.java
和Engine.java
上执行的CRUD操作。
如果有人有更好的解决方案,请发表。
答案 1 :(得分:1)
我看到了四个用Java建模的选项。 请注意,其中大多数都需要调整数据库架构。
一般的问题是,Spring Data JDBC假定引用的实体(Engine
)在其表中具有引用拥有的实体(Car
/ Vehicle
)的列。
出现了一个问题:https://jira.spring.io/browse/DATAJDBC-128
从此开始,您有以下选择:
添加到引擎表的列中,从而导致如下所示的实体和架构(所有实体均减少到与问题相关的最低限度):
public class Car {
@Id
Long id;
String name;
Engine engine;
}
public class Truck {
@Id
Long id;
String name;
Engine engine;
}
public class Engine {
String name;
}
CREATE TABLE CAR (
id BIGINT IDENTITY,
NAME VARCHAR(200)
);
CREATE TABLE TRUCK (
ID BIGINT IDENTITY,
NAME VARCHAR(200)
);
CREATE TABLE ENGINE (
TRUCK BIGINT,
CAR BIGINT,
NAME VARCHAR(200),
FOREIGN KEY (TRUCK) REFERENCES TRUCK (ID),
FOREIGN KEY (CAR) REFERENCES CAR (ID)
);
我在GitHub上提供了完整的示例:https://github.com/schauder/so-sd-jdbc-multipleonetoone。
如果您不喜欢这两列,则可以修改映射以将相同的列用于两个引用。
但是然后您必须确保Car
和Vehicle
的ID是不同的。
即使这样,这种方法仍然存在很大的问题:
deleteAll
存储库或Car
载具上 Truck
将删除所有引擎!
因此不建议采用这种方法!
如果您仍要使用它,则这里是架构和实体的代码。
public class Car {
@Id
Long id;
String name;
@Column(value = "vehicle")
Engine engine;
}
public class Truck {
@Id
Long id;
String name;
@Column(value = "vehicle")
Engine engine;
}
public class Engine {
String name;
}
CREATE TABLE CAR (
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY ,
NAME VARCHAR(200)
);
CREATE TABLE TRUCK (
ID BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH -1, INCREMENT BY -1) PRIMARY KEY ,
NAME VARCHAR(200)
);
CREATE TABLE ENGINE (
VEHICLE BIGINT,
NAME VARCHAR(200),
);
有关此提交的完整示例:https://github.com/schauder/so-sd-jdbc-multipleonetoone/tree/5570979ef85e30fe7a17a8ce48d867fdb79e212a。
具有两个单独的Engine
类和表。
一个用于Car
,一个用于Truck
s。
如果您不希望或无法更改数据库架构,则可以考虑将Engine
,Car
和Truck
分为三个独立的聚合。
您将在Long engineId
和Car
中拥有一个Truck
。
然后可以使用event listener for AfterDeleteEvent
完成级联删除。