简体   繁体   English

Hibernate 关联映射

[英]Hibernate association mapping

I am working on a bike rental system project.我正在从事自行车租赁系统项目。 I am able to do CRUD operations via Rest API on Bike, and Customer and create a Contract object.我可以通过 Bike 和 Customer 上的 Rest API 执行 CRUD 操作,并创建一个 Contract 对象。 For this, I have exposed CRUD endpoints(s) for为此,我公开了 CRUD 端点

  • /bike /自行车
  • /customer /顾客
  • /contract /合同

The POST /contract/final endpoint should return a complete contract overview with contractid, bike details, and customer POST /contract/final 端点应返回完整的合同概览,其中包含合同 ID、自行车详细信息和客户

The association I am using is as below我正在使用的协会如下

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;
}

So I just want to be able to create/modify the bike|customer records and create a contract with the already created customer(s) and bike(s).所以我只想能够创建/修改自行车|客户记录并与已经创建的客户和自行车创建合同。

As of now, the contract request will create the customer and bike records apart from records created separately using /customer, /bike endpoints - which I do not want.截至目前,合同请求将创建客户和自行车记录,而不是使用 /customer、/bike 端点单独创建的记录——这是我不想要的。

Is the association mapping I have used correct for this requirement?我使用的关联映射是否符合此要求? What should ideally be the relationship between these entities given the below contraints?考虑到以下限制,理想情况下这些实体之间的关系应该是什么?

  • One customer can have many contracts but one contract will have only one customer一个客户可以有多个合同,但一个合同将只有一个客户

  • One bike can have many contracts but one contract will have only one bike一辆自行车可以有很多合同,但一份合同只能有一辆自行车

    How can I make use of the existing customer/bike records while creating a contract?在创建合同时如何使用现有的客户/自行车记录?

  1. Do you want to have the ability to change a Bike model when you create a new Contract ?您是否希望在创建新Contract时能够更改Bike型号? Obviously no!显然不是! cascade = CascadeType.ALL is about such changes. cascade = CascadeType.ALL就是关于这样的变化。 So throw it away.所以扔掉它。

  2. Do you want to load all the Contract data, like a Bike , when you load a Contract ?你想在加载Contract时加载所有Contract数据,比如Bike吗? It is not so obvious, but my advice don't do this!这不是很明显,但我的建议是不要这样做! Let's change fetch=FetchType.EAGER to fetch=FetchType.LAZY .让我们将fetch=FetchType.EAGER更改为fetch=FetchType.LAZY

  3. You use two strategies to generate an idstrategy= GenerationType.SEQUENCE , strategy = GenerationType.IDENTITY .您使用两种策略来生成idstrategy= GenerationType.SEQUENCEstrategy = GenerationType.IDENTITY Use only one.只使用一个。

  4. Don't use a primitive type for an id .不要对id使用原始类型。 Change long bikeId to Long bikeId .long bikeId更改为Long bikeId

  5. @JoinColumn specifies a database column name, not a class property. @JoinColumn指定数据库列名,而不是类属性。 Change @JoinColumn(name="customerId") to @JoinColumn(name="CUSTOMER_ID") . @JoinColumn(name="customerId")更改为@JoinColumn(name="CUSTOMER_ID") Use uppercase for column names.对列名使用大写字母。

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;
    
}

Assign existing Bike and Customer to the Contract , using getReferenceById() method.使用getReferenceById()方法将现有的BikeCustomer分配给Contract It doesn't hit a database at all.它根本不会访问数据库。

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

Another way is to use a transient customer.另一种方法是使用临时客户。

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

But standard repository save() method uses merge() .但是标准存储库save()方法使用merge() So it will be an additional SQL request to load a customer.因此加载客户将是一个额外的 SQL 请求。 You can use custom repository with pure save() method to avoid this https://vladmihalcea.com/best-spring-data-jparepository/您可以使用带有纯save()方法的自定义存储库来避免这种情况https://vladmihalcea.com/best-spring-data-jparepository/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM