如何在 POST 主体中发送数据而不在 Spring 引导中设置自动生成的主键值?
How can I send data in POST body without setting the auto generated primary key values in Spring Boot?
我有两个 classes/tables--- 客户和地址具有双向一对一关系。 Address_id 是外键。
这是实体图
我正在尝试通过 postman 发送数据,但我想发送值而不在 post 正文中设置主键属性。如果我只为客户省略 id 属性,它就可以工作。 但是如果我对地址做同样的事情,它就不起作用了。
这是成功插入数据的 post 正文。
<Customer>
<firstName>Dave</firstName>
<lastName>Bautista</lastName>
<gender>M</gender>
<date>2012-01-26T09:00:00.000+0000</date>
<addressdto>
<id>7</id>
<city>BANKURA</city>
<country>WEST BENGAL</country>
</addressdto>
</Customer>
如果我在 addressdto
中省略 <id></id>
那么我会在 postman--
中收到此错误
Failed to add customer due to could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
控制台出错--
2020-04-23 23:10:12.093 ERROR 3824 --- [io-8080-exec-10] o.h.engine.jdbc.spi.SqlExceptionHelper :
Cannot add or update a child row
: a foreign key constraint fails (`liqbtest`.`customers`, CONSTRAINT `FK_DETAIL` FOREIGN KEY
(`address_id`) REFERENCES `address` (`id`))
CustomerDto
package com.spring.liquibase.demo.dto;
import java.util.Date;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import com.sun.xml.txw2.annotation.XmlElement;
@JacksonXmlRootElement(localName = "Customer")
public class CustomerDto {
private int id;
private String firstName;
private String lastName;
private String gender;
private Date date;
private AddressDto addressdto;
public CustomerDto() {
super();
}
..getters and setters
addressDto
public class AddressDto {
private int id;
private String city;
private String country;
public AddressDto() {
super();
}
EntityToDtoMapper
public Customer mapToEntity(CustomerDto customerDto) {
Address address=new Address();
address.setCity(customerDto.getAddressdto().getCity());
address.setCountry(customerDto.getAddressdto().getCountry());
address.setId(customerDto.getAddressdto().getId());
Customer customer=new Customer();
customer.setId(customerDto.getId());
customer.setFirstName(customerDto.getFirstName());
customer.setLastName(customerDto.getLastName());
customer.setGender(customerDto.getGender());
customer.setDate(customerDto.getDate());
customer.setAddress(address);
return customer;
}
家庭控制器
@PostMapping("/customer")
public ResponseEntity<String> addCustomer(@RequestBody CustomerDto customerDto){
String message="";
ResponseEntity<String> finalMessage=null;
try {
Customer customer=mapper.mapToEntity(customerDto);
customerService.addCustomer(customer);
message="Customer with "+customer.getId()+" sucessfully added";
finalMessage= new ResponseEntity<>(message, HttpStatus.OK);
}catch(Exception e) {
message="Failed to add customer due to "+e.getMessage();
finalMessage= new ResponseEntity<>(message, HttpStatus.NOT_ACCEPTABLE);
}
return finalMessage;
}
请告诉我这样做的正确方法是什么,我认为我们不需要提供 id 字段。我该如何处理?
在 EntityToDtoMapper
mapToEntity()
方法中,如果我从 addressDto 中省略 setId()
那么它根本不起作用。
地址实体
@Entity
public class Address {
@Id
private int id;
private String city;
private String country;
@OneToOne(mappedBy="address",cascade=CascadeType.ALL)
private Customer customer;
public Address() {
super();
}
...getters and setters
客户实体
@Entity
@Table(name="customers")
public class Customer {
@Id
private int id;
@Column(name="first_name")
private String firstName;
@Column(name="last_name")
private String lastName;
private String gender;
@Temporal(TemporalType.TIMESTAMP)
private Date date;
@OneToOne(cascade=CascadeType.ALL)
@JoinColumn(name="address_id")
private Address address;
public Customer() {
super();
}
...getters an setters
将 @GeneratedValue
添加到您的 ID 字段以正确自动生成实体 ID。请更改
@Id
private int id;
到
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", unique = true, nullable = false)
在您的两个实体上。
然后在您的 mapToEntity
方法中添加行:
address.setCustomer(customer);
通过将新字段变量添加为 addressId
来更改您的 Customer
实体
@Entity
@Table(name="customers")
public class Customer {
@Id
private int id;
@Column(name="first_name")
private String firstName;
@Column(name="last_name")
private String lastName;
private String gender;
@Column(name="address_id")
private int addressId;
@Temporal(TemporalType.TIMESTAMP)
private Date date;
@OneToOne(cascade=CascadeType.ALL)
@JoinColumn(name="address_id")
private Address address;
public Customer() {
super();
}
}
并如下更改 EntityDTOMapper
public Customer mapToEntity(CustomerDto customerDto) {
Address address=new Address();
address.setCity(customerDto.getAddressdto().getCity());
address.setCountry(customerDto.getAddressdto().getCountry());
address.setId(customerDto.getAddressdto().getId());
Customer customer=new Customer();
customer.setId(customerDto.getId());
customer.setFirstName(customerDto.getFirstName());
customer.setLastName(customerDto.getLastName());
customer.setGender(customerDto.getGender());
customer.setDate(customerDto.getDate());
customer.setAddressId(customerDto.getAddressdto().getId());
//customer.setAddress(address);
return customer;
}
我有两个 classes/tables--- 客户和地址具有双向一对一关系。 Address_id 是外键。
这是实体图
我正在尝试通过 postman 发送数据,但我想发送值而不在 post 正文中设置主键属性。如果我只为客户省略 id 属性,它就可以工作。 但是如果我对地址做同样的事情,它就不起作用了。
这是成功插入数据的 post 正文。
<Customer>
<firstName>Dave</firstName>
<lastName>Bautista</lastName>
<gender>M</gender>
<date>2012-01-26T09:00:00.000+0000</date>
<addressdto>
<id>7</id>
<city>BANKURA</city>
<country>WEST BENGAL</country>
</addressdto>
</Customer>
如果我在 addressdto
中省略 <id></id>
那么我会在 postman--
Failed to add customer due to could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
控制台出错--
2020-04-23 23:10:12.093 ERROR 3824 --- [io-8080-exec-10] o.h.engine.jdbc.spi.SqlExceptionHelper :
Cannot add or update a child row
: a foreign key constraint fails (`liqbtest`.`customers`, CONSTRAINT `FK_DETAIL` FOREIGN KEY
(`address_id`) REFERENCES `address` (`id`))
CustomerDto
package com.spring.liquibase.demo.dto;
import java.util.Date;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import com.sun.xml.txw2.annotation.XmlElement;
@JacksonXmlRootElement(localName = "Customer")
public class CustomerDto {
private int id;
private String firstName;
private String lastName;
private String gender;
private Date date;
private AddressDto addressdto;
public CustomerDto() {
super();
}
..getters and setters
addressDto
public class AddressDto {
private int id;
private String city;
private String country;
public AddressDto() {
super();
}
EntityToDtoMapper
public Customer mapToEntity(CustomerDto customerDto) {
Address address=new Address();
address.setCity(customerDto.getAddressdto().getCity());
address.setCountry(customerDto.getAddressdto().getCountry());
address.setId(customerDto.getAddressdto().getId());
Customer customer=new Customer();
customer.setId(customerDto.getId());
customer.setFirstName(customerDto.getFirstName());
customer.setLastName(customerDto.getLastName());
customer.setGender(customerDto.getGender());
customer.setDate(customerDto.getDate());
customer.setAddress(address);
return customer;
}
家庭控制器
@PostMapping("/customer")
public ResponseEntity<String> addCustomer(@RequestBody CustomerDto customerDto){
String message="";
ResponseEntity<String> finalMessage=null;
try {
Customer customer=mapper.mapToEntity(customerDto);
customerService.addCustomer(customer);
message="Customer with "+customer.getId()+" sucessfully added";
finalMessage= new ResponseEntity<>(message, HttpStatus.OK);
}catch(Exception e) {
message="Failed to add customer due to "+e.getMessage();
finalMessage= new ResponseEntity<>(message, HttpStatus.NOT_ACCEPTABLE);
}
return finalMessage;
}
请告诉我这样做的正确方法是什么,我认为我们不需要提供 id 字段。我该如何处理?
在 EntityToDtoMapper
mapToEntity()
方法中,如果我从 addressDto 中省略 setId()
那么它根本不起作用。
地址实体
@Entity
public class Address {
@Id
private int id;
private String city;
private String country;
@OneToOne(mappedBy="address",cascade=CascadeType.ALL)
private Customer customer;
public Address() {
super();
}
...getters and setters
客户实体
@Entity
@Table(name="customers")
public class Customer {
@Id
private int id;
@Column(name="first_name")
private String firstName;
@Column(name="last_name")
private String lastName;
private String gender;
@Temporal(TemporalType.TIMESTAMP)
private Date date;
@OneToOne(cascade=CascadeType.ALL)
@JoinColumn(name="address_id")
private Address address;
public Customer() {
super();
}
...getters an setters
将 @GeneratedValue
添加到您的 ID 字段以正确自动生成实体 ID。请更改
@Id
private int id;
到
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", unique = true, nullable = false)
在您的两个实体上。
然后在您的 mapToEntity
方法中添加行:
address.setCustomer(customer);
通过将新字段变量添加为 addressId
Customer
实体
@Entity
@Table(name="customers")
public class Customer {
@Id
private int id;
@Column(name="first_name")
private String firstName;
@Column(name="last_name")
private String lastName;
private String gender;
@Column(name="address_id")
private int addressId;
@Temporal(TemporalType.TIMESTAMP)
private Date date;
@OneToOne(cascade=CascadeType.ALL)
@JoinColumn(name="address_id")
private Address address;
public Customer() {
super();
}
}
并如下更改 EntityDTOMapper
public Customer mapToEntity(CustomerDto customerDto) {
Address address=new Address();
address.setCity(customerDto.getAddressdto().getCity());
address.setCountry(customerDto.getAddressdto().getCountry());
address.setId(customerDto.getAddressdto().getId());
Customer customer=new Customer();
customer.setId(customerDto.getId());
customer.setFirstName(customerDto.getFirstName());
customer.setLastName(customerDto.getLastName());
customer.setGender(customerDto.getGender());
customer.setDate(customerDto.getDate());
customer.setAddressId(customerDto.getAddressdto().getId());
//customer.setAddress(address);
return customer;
}