我正在做一个自行车租赁系统项目。我可以通过Rest API在Bike和Customer上执行CRUD操作,并创建一个Contract对象。为此,我公开了
- /自行车
- /客户
- /合同
POST/contract/final端点应返回包含contractid、自行车详细信息和customer的完整合同概述
我使用的关联如下
class Contract {
@Id
@GeneratedValue(strategy= GenerationType.SEQUENCE)
private id;
@ManyToOne(fetch=FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name="customerId")
private Customer customer;
@ManyToOne(fetch=FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name="bikeId")
private Bike bike;
}
class Customer{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "customer_id")
private Long customerId;
private String firstName;
}
class Bike{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "bike_id")
private long bikeId;
private String model;
}
因此,我只希望能够创建/修改自行车|客户记录并与已经创建的客户和自行车创建合同。
到目前为止,合同请求将创建客户和自行车记录,而不是使用/customer,/bike端点单独创建的记录-这是我不希望的。
我所使用的关联Map对于这个需求是正确的吗?在下面的约束条件下,这些实体之间的理想关系应该是什么?
- 一个客户可以有多个合同,但一个合同只能有一个客户
- 一辆自行车可以有多个合同,但一个合同只能有一辆自行车
在创建合同时,如何利用现有的客户/自行车记录?
1条答案
按热度按时间rggaifut1#
1.当你创建一个新的
Contract
时,你想拥有改变Bike
模型的能力吗?显然不是!cascade = CascadeType.ALL
是关于这样的改变的。所以扔掉它吧。1.当你加载一个
Contract
的时候,你想加载所有的Contract
数据,就像Bike
一样吗?这不是很明显,但是我的建议是不要这样做!让我们把fetch=FetchType.EAGER
改为fetch=FetchType.LAZY
。1.生成
id
-strategy= GenerationType.SEQUENCE
,strategy = GenerationType.IDENTITY
需要使用两种策略,但只能使用一种。1.不要对
id
使用基元类型。将long bikeId
更改为Long bikeId
。@JoinColumn
指定数据库列名,而不是类属性。将@JoinColumn(name="customerId")
更改为@JoinColumn(name="CUSTOMER_ID")
。列名使用大写。使用
getReferenceById()
方法将现有的Bike
和Customer
分配给Contract
,它根本不会命中数据库。另一种方法是使用临时客户。
但是标准存储库
save()
方法使用merge()
。因此,加载客户将是一个额外的SQL请求。您可以使用具有纯save()
方法的自定义存储库来避免此https://vladmihalcea.com/best-spring-data-jparepository/