Spring 保存新记录时的OneToOne CONSTRAINTVIOLION,PK提供
我们有一个名为Spring 保存新记录时的OneToOne CONSTRAINTVIOLION,PK提供,spring,hibernate,spring-boot,jpa,Spring,Hibernate,Spring Boot,Jpa,我们有一个名为客户的实体,它与该实体的地址有一对一的关系 客户的主键应手动定义。应自动定义地址”主键 因此,在Customer中,我省略了@GeneratedValue并手动提供is值。但是,在尝试保存时,我遇到以下错误: 2018-11-07 10:42:17.810 ERROR 1257 --- [nio-8080-exec-2] o.h.i.ExceptionMapperStandardImpl : HHH000346: Error during managed flush
客户
的实体,它与该实体的地址
有一对一的关系
客户的主键应手动定义。应自动定义地址
”主键
因此,在Customer
中,我省略了@GeneratedValue
并手动提供is值。但是,在尝试保存时,我遇到以下错误:
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}'}
问题是提供了地址.street
,我不明白为什么JPA抱怨它是空的
下面是我试图保存的JSON主体。(正在正确反序列化,因为地址不为空)
以下是客户实体:
@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> {
}
通过阅读Hibernate文档,save操作只保存具有自动生成ID的实体。因此,如果您打算自己设置id,那么您需要的是更改persist的insert方法。由于您的客户的id不是自动生成的,所以这可能就是问题所在。你可以在这本书里读到更多
希望有帮助。如果您添加CascadeType.MERGE,它会工作的
@OneToOne(fetch = FetchType.EAGER, cascade = { CascadeType.PERSIST, CascadeType.MERGE})
@JoinColumn(name = "address_id")
private Address address;
您设置了客户id(50),以便执行以下行的SimpleParepository
return this.em.merge(entity);
不应该是@JoinColumn(name=“address\u Id”)
?我试图更改@JoinColumn(name=“address\u Id”)
,但没有成功。您能给我们显示保存实体的代码吗?当然!我编辑了答案以提供此信息@AlainCruzIf如果删除OneToOne关系,记录将成功保存。我认为问题与关系本身有关……有没有办法使Address.Address\u Id与Customer(Customer.Customer\u Id)的密钥相同?例如,如果我发布一个customer_id=50的客户,如何生成Address.Address_id也假定值为“50”?你的意思是,拥有属于该地址的客户列表?或者该地址Id与客户的地址Id相同?地址Id与客户的地址Id相同。唯一的方法是删除@GeneratedValue(strategy=GenerationType.IDENTITY)
并手动设置Id。类似于customer.setId(1);address.setId(customer.getId())代码>。无论如何,您已经自己设置了客户id。好的,但是这样我需要手动执行customer.getAddress().setCustomerId(customer.getCustomerId())?这不是有点黑吗?你不需要它。通过添加这种级联类型,您只需要调用存储库的save方法。我认为你们的关系是单向的(客户到地址),所以我的测试是单向的。如果设置id,hibernate将调用merge方法,这是很自然的。我在这里尝试了这种方法,但没有达到预期效果。当我第一次发布数据时,JPA创建了两条记录:ID=50的CustomerID和ID=1的Address。如果我再次发布相同的数据,则会更新客户(因为我有CustomerID),但地址会用新ID复制(在本例中为2)。这是因为提交的JSON上没有“地址\ id”。
@PostMapping
public Customer postCustomer(@RequestBody Customer customer) {
return customerRepository.persist(customer);
}
@OneToOne(fetch = FetchType.EAGER, cascade = { CascadeType.PERSIST, CascadeType.MERGE})
@JoinColumn(name = "address_id")
private Address address;
return this.em.merge(entity);