Spring Boot Hibernate关联Map

fhg3lkii  于 2022-12-23  发布在  Spring
关注(0)|答案(1)|浏览(180)

我正在做一个自行车租赁系统项目。我可以通过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对于这个需求是正确的吗?在下面的约束条件下,这些实体之间的理想关系应该是什么?

  • 一个客户可以有多个合同,但一个合同只能有一个客户
  • 一辆自行车可以有多个合同,但一个合同只能有一辆自行车

在创建合同时,如何利用现有的客户/自行车记录?

rggaifut

rggaifut1#

1.当你创建一个新的Contract时,你想拥有改变Bike模型的能力吗?显然不是!cascade = CascadeType.ALL是关于这样的改变的。所以扔掉它吧。
1.当你加载一个Contract的时候,你想加载所有的Contract数据,就像Bike一样吗?这不是很明显,但是我的建议是不要这样做!让我们把fetch=FetchType.EAGER改为fetch=FetchType.LAZY
1.生成id-strategy= GenerationType.SEQUENCEstrategy = GenerationType.IDENTITY需要使用两种策略,但只能使用一种。
1.不要对id使用基元类型。将long bikeId更改为Long bikeId

  1. @JoinColumn指定数据库列名,而不是类属性。将@JoinColumn(name="customerId")更改为@JoinColumn(name="CUSTOMER_ID")。列名使用大写。
class Contract {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID")
    private Long id;
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "CUSTOMER_ID")
    private Customer customer;
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "BIKE_ID")
    private Bike bike;
    
}

使用getReferenceById()方法将现有的BikeCustomer分配给Contract,它根本不会命中数据库。

Customer customer = customerRepository.getReferenceById(customerId);
contract.setCustomer(customer);

另一种方法是使用临时客户。

Customer customer = new Customer();
customer.setId(customerId);
contract.setCustomer(customer);

但是标准存储库save()方法使用merge()。因此,加载客户将是一个额外的SQL请求。您可以使用具有纯save()方法的自定义存储库来避免此https://vladmihalcea.com/best-spring-data-jparepository/

相关问题