SpringBoot JPA 关系 - 如果对象存在,则防止创建新实体,而是返回已存在的对象

问题描述

我有一个使用控制器、服务和存储库逻辑构建的客户实体。

而且我还有一个 Address 实体,只有一个简单的 POJO 和 @onetoMany 注释。

如果我使用相同地址属性发出两个 POST 请求 - 我如何告诉我的应用程序如果这些地址属性已经存在数据库 - 阻止数据库添加一个新实体,而是返回已经存在的实体?

例如POST 请求:

// First request
{
    "name": "Foo","contact": "123456","email": "Foo@gmail.com","address": {
        "street": "Wall street","postalCode": 10,"houseNo": "45","city": "New York"
    }
}

// Second request
{
    "name": "Bar","contact": "5321","email": "Bar@gmail.com",<----- same as first request
        "postalCode": 10,<----- same as first request
        "houseNo": "45",<----- same as first request
        "city": "New York" <----- same as first request
    }
}

这是获取所有客户时的结果:

[
    {
        "id": 1,"name": "Foo","address": {
            "id": 1,"street": "Wall street","city": "New York"
        }
    },{
        "id": 2,"name": "Bar","address": {
            "id": 2,<---------------- expect this ID to be 1 
            "street": "Wall street","city": "New York"
        }
    }
]

这是帮助我进行我的小项目所需的必要信息(如果)。

Customer.java

@JsonIdentityInfo(
        generator = ObjectIdGenerators.PropertyGenerator.class,property = "id")
@Entity
@Table
public class Customer {
    @Id
    @SequenceGenerator(
            name = "customer_sequence",sequenceName = "customer_sequence",allocationSize = 1
    )
    @GeneratedValue(
            strategy = GenerationType.SEQUENCE,generator = "customer_sequence"
    )
    private Long id;
    private String name;
    private String contact;
    private String email;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "address_id",nullable = false)
    private Address address;
    [...]

Address.java

@JsonIdentityInfo(
        generator = ObjectIdGenerators.PropertyGenerator.class,property = "id")
@Entity
@Table
public class Address {
    @Id
    @SequenceGenerator(
            name = "address_sequence",sequenceName = "address_sequence",generator = "address_sequence"
    )
    private Long id;
    private String street;
    private int postalCode;
    private String houseNo;
    private String city;

    @JsonIgnore
    @OnetoMany(mappedBy = "address")
    private Set<Customer> customers;
    [...]

CustomerController.java

//...
@PostMapping
    public void createCustomer(@RequestBody Customer customer) {
        customerService.createCustomer(customer);
    }

[...]

以及将客户保存到数据库服务

//...
public void createCustomer(Customer customer) {
        customerRepository.save(customer);
    }

[...]

解决方法

您可以使用您的地址参数创建一个哈希值并保持不变;

"street": "Wall street","postalCode": 10,"houseNo": "45","city": "New York"
"uid": "3rn3u924917vt8r78b17vxver"

当你得到一个新地址时,你可以用它创建一个散列,然后用那个散列来获取地址。如果该哈希值存在任何地址,请获取该地址并将其放入您的客户对象中并保存。

,

所以我通过做一些小的更改设法不创建重复的地址。

首先,我在 Address 类中自动生成了 equals()

@Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Address address = (Address) o;
        return postalCode == address.postalCode && street.equals(address.street) && houseNo.equals(address.houseNo) && city.equals(address.city);
    }

在我创建客户的服务中,我实现了此代码以检查是否有任何客户与新客户具有相同的地址:

public void createCustomer(Customer customer) {
        Optional<Customer> customerWithExistingAddress = customerRepository.findAll()
                .stream()
                .filter(x -> x.getAddress().equals(customer.getAddress()))
                .findFirst();

        customerWithExistingAddress.ifPresent(c -> customer.setAddress(c.getAddress()));

        customerRepository.save(customer);
    }

现在如果已经存在,它不会创建新实体。