OneToOne ConstraintViolation同时保存新记录,提供PK

时间:2018-11-07 12:59:01

标签: spring hibernate spring-boot jpa

我们有一个名为Customers的实体,它与实体Address具有OneToOne关系。

Customer的PK应该手动定义。 Address的PK应该自动定义。

因此,在Customer中,我省略了@GeneratedValue,而是手动提供了价值。但是,当尝试保存时,出现以下错误:

2018-11-07 10:42:17.810 ERROR 1257 --- [nio-8080-exec-2] o.h.i.ExceptionMapperStandardImpl        : HHH000346: Error during managed flush [Validation failed for classes [br.com.customers.entity.Address] during persist time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
    ConstraintViolationImpl{interpolatedMessage='não pode ser nulo', propertyPath=street, rootBeanClass=class br.com.customers.entity.Address, messageTemplate='{javax.validation.constraints.NotNull.message}'}

问题是提供了address.street,我不知道为什么JPA抱怨它为空...

这是我要保存的JSON正文。 (正在正确反序列化,因为Address不为NULL)

{
    "customer_Id": 50,
    "name": "name",
    "company_name": "company_name",
    "email": "email@provider.com",
    "business_phone": "(00) 1111-2222",
    "mobile_phone": "(00) 1111-2222",
    "document": "123456789",
    "state_registration_number": "ISENTO",
    "state_registration_type": "NO_CONTRIBUTOR",
    "city_registration_number": "ISENTO",
    "classification": "AUTO",
    "address": {
        "street": "STREET NAME",
        "number": "NUMBER",
        "complement": "COMPLEMENT",
        "zip_code": "ZIP_CODE",
        "neighborhood": "NEIGHBORHOOD",
        "city": "CITY",
        "state": "STATE"
    }
}

这里是客户实体:

@Data
@Entity(name = "X_CUSTOMERS")
public class Customer {

    @Id
    private int customer_Id;

    @NotNull
    private String name;

    private String company_name;

    private String email;

    private String business_phone;

    private String mobile_phone;

    @NotNull
    private String document;

    private String state_registration_number;

    private String state_registration_type;

    private String city_registration_number;

    @NotNull
    private String classification;

    @OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
    @JoinColumn(name = "address_id")
    private Address address;

}

在这里,地址实体:

@Data
@Entity(name = "X_ADDRESS")
public class Address {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int address_Id;

    @NotNull
    private String street;

    private String number;

    private String complement;

    private String zip_code;

    private String neighborhood;

    private String city;

    private String state;

}

我做错了什么? 谢谢!!!


添加代码确实会保留实体:

客户资料库:

public interface CustomerRepository extends JpaRepository<Customer, Integer> {

}

要坚持下去:

@RestController
@RequestMapping("/customers")
public class CustomersController {

    private CustomerRepository customerRepository;

    public CustomersController(CustomerRepository customerRepository) {
        this.customerRepository = customerRepository;
    }

    @PostMapping
    public Customer postCustomer(@RequestBody Customer customer) {
        return customerRepository.save(customer);
    }


}

2 个答案:

答案 0 :(得分:1)

通过阅读Hibernate文档,保存操作仅保留具有自动生成ID的实体。因此,如果您打算自己设置id,那么您需要的是将insert方法更改为persist。并且由于您的客户的ID并非自动生成,因此可能是问题所在。您可以在此blog中阅读更多内容。

@PostMapping
public Customer postCustomer(@RequestBody Customer customer) {
    return customerRepository.persist(customer);
}

希望有帮助。

答案 1 :(得分:0)

如果添加CascadeType.MERGE,它将正常工作

@OneToOne(fetch = FetchType.EAGER, cascade = { CascadeType.PERSIST, CascadeType.MERGE})
    @JoinColumn(name = "address_id")
    private Address address;

您设置了客户id(50),因此将执行下面的SimpleJpaRepository行。

return this.em.merge(entity);