在Spring Boot JPA中,我们通常有像@OneToMany
这样的实体关系来映射到像1:M这样的数据库关系。
如果我们有像Car和Part这样的实体,其中Car是关系的1侧,Part是关系的M侧,这是可以的。在这种情况下,这是可以的,因为两个表中的数据都是"0";相关的";我们希望同时从两个表中插入或获取相关数据。
在这种情况下,我们的汽车实体将具有OneToMany类:
@Entity(name = "car")
public class CarEntity {
...
@Id @GeneratedValue(...)
private Long id;
@OneToMany(mappedBy = "carDetails", cascade = CascadeType.ALL)
private List<PartEntity> parts;
}
和Part实体将具有ManyToOne类:
@Entity(name = "part")
public class PartEntity {
...
@ManyToOne
@JoinColumn(name = "car_id")
private CarEntity carDetails;
}
,这很好。
为了保持日期,我们必须在有效载荷中提供一个JSON有效载荷,其中包含汽车及其零件的数据,以便保存汽车和零件:
{
"vendor": "Toyota",
"model": "Camry"
"parts": [
{
"gasket": "A103",
"price": "16"
},
{
"tire": "Good year",
"price": "149"
}
]
}
,这将使汽车及其零部件持久存在于存储库中。
检索时也是如此。取回汽车也会取回它的零件。
这一切都很清楚。
然而,我们可能有一个1:M的关系,其中M中的数据是"0";有点不相关的";到关系的一侧的数据。
例如,假设我们记录事件是为了审计目的。每个事件都记录在event表中。但我们也想将此事件转发到某个下游的API,因此我们也会在event_log表中记录该事件是否发送到该下游的API。
因此,我们有EVENT:EVENT_LOG1:M关系,其中一个EVENT可以有多个EVENT_LOG。在这种情况下,EVENT_LOG是";未释放的";因为它只是用于日志记录/审计目的的数据,不应该是POST和GET请求中JSON负载的一部分。
假设我们有以下表格定义:
EVENT[ID (PK), NAME, DATE]
EVENT_LOG[ID (PK), EVENT_ID (FK), SENT, DATE]
上面,PKs和DATEs字段由数据库处理,SENT字段默认为0表示尚未发送(1=已发送(。例如:
EVENT [1, 'save_data_event', 2022-10-12T15:17:001]
EVENT_LOG [1, 1, 0, 2022-10-12T15:17:002] // 0 = default (not sent)
在这里,我们希望发送只包含相关EVENT数据的JSON有效载荷:
{
"vendor": "some_data_event"
}
这将像上面一样填充EVENT表。然而,在Entity类中使用上面的@OneToMany关系,它不会在EVENT_LOG中填充数据,这不是我们想要的。我们希望他们都有人居住。
类似地,在获取数据时,我们只希望从EVENT表中获取相关数据,因为EVENT_LOG数据不感兴趣,并且它不应包含在JSON GET有效负载中。
如何做到这一点?
假设您使用Jackson,您可能会使用@JsonIgnore
来忽略JSON生成的属性。
我认为以上是黑客行为。正确的做法是按照域驱动设计的建议,将您的域模型分解为聚合,并且我们只在聚合之间引用id。我在SpringDataJDBC的上下文中写了一篇关于这一点的文章,但这个概念也可以而且可以说应该应用于JPA。