Java Springboot 2.1.9.RELEASE-使用JPA持久化具有父子关系的实体
我在mysql中的Java Springboot 2.1.9.RELEASE-使用JPA持久化具有父子关系的实体,java,mysql,json,jpa,Java,Mysql,Json,Jpa,我在mysql中的Employee和Address表之间有一对多关系。我希望在使用子数据持久化父对象时,首先创建父对象,并在子表中自动使用其parent\u id。我得到以下错误 任何帮助都将不胜感激: 父代码: @Entity @Table(name = "employee") public class Employee implements Serializable { private static final long serialVersionUID = 1L
Employee
和Address
表之间有一对多关系。我希望在使用子数据持久化父对象时,首先创建父对象,并在子表中自动使用其parent\u id
。我得到以下错误
任何帮助都将不胜感激:
父代码:@Entity
@Table(name = "employee")
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(length = 6)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Temporal(TemporalType.DATE)
private Date dob;
@Column(name="email_address")
private String emailAddress;
@Column(name="first_name")
private String firstName;
@Column(name="gender")
private String gender;
@Column(name="last_name")
private String lastName;
@Column(name="user_id")
private String userName;
@Column(name="password")
private String password;
@Column(name="email_verified")
private String emailVerification;
@OneToMany(targetEntity = Address.class, mappedBy = "employee", orphanRemoval = true,
cascade =
CascadeType.ALL, fetch = FetchType.EAGER)
private Set<Address> addresses = null;
public Employee() {
}
public Employee(long id) {
this.id = id;
}
控制器:
@CrossOrigin (origins = "*" )
@PostMapping("/employee")
public Employee createEmployee(@Valid @RequestBody Employee employee) {
return employeeRepository.save(employee);
}
JSON输入:
{
"dob": "2001-11-12",
"emailAddress": "aaa@gmail.com",
"firstName": "John",
"gender": "M",
"lastName": "Wilson",
"userName": "jon",
"password": "pass",
"emailVerification": null,
"addresses": [
{
"address1": "123 My Street",
"address2": null,
"city": "MyCity1",
"zip": "11111",
"stateId": 1
},
{
"address1": "567 My Street",
"address2": null,
"city": "MyCity2",
"zip": "22222",
"stateId": 1
}
]
}
错误
一个选项是遍历所有地址并手动设置
employee
属性。您应该手动执行,因为JSON反序列化将不会触及该字段,即使没有@JsonIgnore
注释。但这只是问题的表面
您正在employee
属性上设置updateable=false,insertable=false
。另一个属性是字符串empId
,它映射到同一列,表示您希望手动管理关系。列/属性的类型应与相关实体的PK/id相同,因此long
!而且,考虑到JSON也不包含empId
,您仍然需要手动设置它;但是你在创造的时候还不知道!如果删除Address.empId
属性和updateable=false,insertable=false
并手动设置employee
,它应该可以工作
如果您希望Jackson为您这样做,除了上一段中讨论的任务外,还可以在Employee.addresses
属性上使用@JsonManagedReference
,在Address.Employee
属性上使用@JsonBackReference
(删除updateable=false,insertable=false
和字符串empId
属性)并当然删除@JsonIgnore
。请参阅详细说明:
@JsonManagedReference
@OneToMany(targetEntity=Address.class,mappedBy=“employee”,orphanRemoving=true,cascade=CascadeType.ALL,fetch=FetchType.EAGER)
专用地址集=空;
@JsonBackReference
@manytone(fetch=FetchType.LAZY,可选=false)
@JoinColumn(name=“emp_id”,nullable=false)
私人雇员;
免责声明:我反对混合使用JPA和Jackson注释。这确实很方便,因为您不需要单独的DTO类,不需要映射逻辑,也不需要担心执行转换实体所需的CPU/内存↔ DTO。另一方面,数据传输和数据持久性是两个完全不同的关注点,因此SOLID将付诸东流。并且有可能发送客户端不应该看到的字段(例如用户的密码或电子邮件)。有效。非常感谢!!!
{
"dob": "2001-11-12",
"emailAddress": "aaa@gmail.com",
"firstName": "John",
"gender": "M",
"lastName": "Wilson",
"userName": "jon",
"password": "pass",
"emailVerification": null,
"addresses": [
{
"address1": "123 My Street",
"address2": null,
"city": "MyCity1",
"zip": "11111",
"stateId": 1
},
{
"address1": "567 My Street",
"address2": null,
"city": "MyCity2",
"zip": "22222",
"stateId": 1
}
]
}
Hibernate:
insert
into
address
(address1, address2, city, emp_id, state_id, zip)
values
(?, ?, ?, ?, ?, ?)
2021-04-28 22:17:19.067 RACE 25508 --- [nio-9090-exec-2] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [VARCHAR] - [567 My Street]
2021-04-28 22:17:19.067 TRACE 25508 --- [nio-9090-exec-2] o.h.type.descriptor.sql.BasicBinder : binding parameter [2] as [VARCHAR] - [null]
2021-04-28 22:17:19.067 TRACE 25508 --- [nio-9090-exec-2] o.h.type.descriptor.sql.BasicBinder : binding parameter [3] as [VARCHAR] - [MyCity2]
2021-04-28 22:17:19.067 TRACE 25508 --- [nio-9090-exec-2] o.h.type.descriptor.sql.BasicBinder : binding parameter [4] as [VARCHAR] - [null]
2021-04-28 22:17:19.067 TRACE 25508 --- [nio-9090-exec-2] o.h.type.descriptor.sql.BasicBinder : binding parameter [5] as [INTEGER] - [1]
2021-04-28 22:17:19.067 TRACE 25508 --- [nio-9090-exec-2] o.h.type.descriptor.sql.BasicBinder : binding parameter [6] as [VARCHAR] - [22222]
2021-04-28 22:17:19.071 WARN 25508 --- [nio-9090-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1048, SQLState: 23000
2021-04-28 22:17:19.071 ERROR 25508 --- [nio-9090-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper : Column 'emp_id' cannot be null
2021-04-28 22:17:19.094 WARN 25508 --- [nio-9090-exec-2] .m.m.a.ExceptionHandlerExceptionResolver : Resolved [org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null];