我有以下3个域模型对象,其中appuser具有以下等级和培训状态。 Get调用返回JSON对象时工作正常,但在JPA中添加Model对象时出错。
Cannot handle managed/back reference 'defaultReference': no back reference property found from type [simple type, class com.springboot.model.Rank
`
package com.springboot.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonManagedReference;
@Entity
@Table(name = "app_user", catalog = "testdb")
public class AppUser implements java.io.Serializable {
private Integer id;
private Rank rank;
private Trainingstatus trainingstatus;
private String name;
private int age;
private double salary;
public AppUser() {
}
public AppUser(Rank rank, Trainingstatus trainingstatus, String name, int age, double salary) {
this.rank = rank;
this.trainingstatus = trainingstatus;
this.name = name;
this.age = age;
this.salary = salary;
}
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "id", unique = true, nullable = false)
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "rankId", nullable = false)
@JsonManagedReference
public Rank getRank() {
return this.rank;
}
public void setRank(Rank rank) {
this.rank = rank;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "trainingStatusId", nullable = false)
@JsonManagedReference
public Trainingstatus getTrainingstatus() {
return this.trainingstatus;
}
public void setTrainingstatus(Trainingstatus trainingstatus) {
this.trainingstatus = trainingstatus;
}
@Column(name = "name", nullable = false, length = 30)
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
@Column(name = "age", nullable = false)
public int getAge() {
return this.age;
}
public void setAge(int age) {
this.age = age;
}
@Column(name = "salary", nullable = false, precision = 22, scale = 0)
public double getSalary() {
return this.salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}
package com.springboot.model;
// Generated 28 Apr, 2018 5:35:48 PM by Hibernate Tools 4.3.5.Final
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonManagedReference;
/**
* Trainingstatus generated by hbm2java
*/
@Entity
@Table(name = "trainingstatus", catalog = "testdb")
public class Trainingstatus implements java.io.Serializable {
private Integer trainingStatusId;
private String trainingStatus;
private String lastUpdatedBy;
private Date lastUpdatedDate;
private Set<AppUser> appUsers = new HashSet<AppUser>(0);
public Trainingstatus() {
}
public Trainingstatus(String trainingStatus, String lastUpdatedBy, Date lastUpdatedDate) {
this.trainingStatus = trainingStatus;
this.lastUpdatedBy = lastUpdatedBy;
this.lastUpdatedDate = lastUpdatedDate;
}
public Trainingstatus(String trainingStatus, String lastUpdatedBy, Date lastUpdatedDate, Set<AppUser> appUsers) {
this.trainingStatus = trainingStatus;
this.lastUpdatedBy = lastUpdatedBy;
this.lastUpdatedDate = lastUpdatedDate;
this.appUsers = appUsers;
}
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "trainingStatusId", unique = true, nullable = false)
public Integer getTrainingStatusId() {
return this.trainingStatusId;
}
public void setTrainingStatusId(Integer trainingStatusId) {
this.trainingStatusId = trainingStatusId;
}
@Column(name = "trainingStatus", nullable = false, length = 45)
public String getTrainingStatus() {
return this.trainingStatus;
}
public void setTrainingStatus(String trainingStatus) {
this.trainingStatus = trainingStatus;
}
@Column(name = "lastUpdatedBy", nullable = false, length = 45)
public String getLastUpdatedBy() {
return this.lastUpdatedBy;
}
public void setLastUpdatedBy(String lastUpdatedBy) {
this.lastUpdatedBy = lastUpdatedBy;
}
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "lastUpdatedDate", nullable = false, length = 19)
public Date getLastUpdatedDate() {
return this.lastUpdatedDate;
}
public void setLastUpdatedDate(Date lastUpdatedDate) {
this.lastUpdatedDate = lastUpdatedDate;
}
@OneToMany(fetch = FetchType.LAZY, mappedBy = "trainingstatus")
@JsonBackReference
// @JsonIgnore
public Set<AppUser> getAppUsers() {
return this.appUsers;
}
public void setAppUsers(Set<AppUser> appUsers) {
this.appUsers = appUsers;
}
}
package com.springboot.model;
// Generated 28 Apr, 2018 5:35:48 PM by Hibernate Tools 4.3.5.Final
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import com.fasterxml.jackson.annotation.JsonBackReference;
@Entity
@Table(name = "rank", catalog = "testdb")
public class Rank implements java.io.Serializable {
private Integer rankId;
private String rank;
private String lastUpdatedBy;
private Date lastUpdatedDate;
private Set<AppUser> appUsers = new HashSet<AppUser>(0);
public Rank() {
}
public Rank(String rank, String lastUpdatedBy, Date lastUpdatedDate) {
this.rank = rank;
this.lastUpdatedBy = lastUpdatedBy;
this.lastUpdatedDate = lastUpdatedDate;
}
public Rank(String rank, String lastUpdatedBy, Date lastUpdatedDate, Set<AppUser> appUsers) {
this.rank = rank;
this.lastUpdatedBy = lastUpdatedBy;
this.lastUpdatedDate = lastUpdatedDate;
this.appUsers = appUsers;
}
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "rankId", unique = true, nullable = false)
public Integer getRankId() {
return this.rankId;
}
public void setRankId(Integer rankId) {
this.rankId = rankId;
}
@Column(name = "rank", nullable = false, length = 45)
public String getRank() {
return this.rank;
}
public void setRank(String rank) {
this.rank = rank;
}
@Column(name = "lastUpdatedBy", nullable = false, length = 45)
public String getLastUpdatedBy() {
return this.lastUpdatedBy;
}
public void setLastUpdatedBy(String lastUpdatedBy) {
this.lastUpdatedBy = lastUpdatedBy;
}
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "lastUpdatedDate", nullable = false, length = 19)
public Date getLastUpdatedDate() {
return this.lastUpdatedDate;
}
public void setLastUpdatedDate(Date lastUpdatedDate) {
this.lastUpdatedDate = lastUpdatedDate;
}
@OneToMany(fetch = FetchType.LAZY, mappedBy = "rank")
@JsonBackReference
// @JsonIgnore
public Set<AppUser> getAppUsers() {
return this.appUsers;
}
public void setAppUsers(Set<AppUser> appUsers) {
this.appUsers = appUsers;
}
}
从我的其他应用程序中,我正在添加AppUser父对象,如下所示:
@RequestMapping(value = "/user/", method = RequestMethod.POST)
public ResponseEntity<?> createUser(@RequestBody AppUser user, UriComponentsBuilder ucBuilder) {
logger.info("Creating AppUser : {}", user);
if (userService.isUserExist(user)) {
logger.error("Unable to create. A AppUser with name {} already exist", user.getName());
return new ResponseEntity(new CustomErrorType("Unable to create. A AppUser with name " +
user.getName() + " already exist."),HttpStatus.CONFLICT);
}
userService.saveUser(user);
HttpHeaders headers = new HttpHeaders();
headers.setLocation(ucBuilder.path("/api/user/{id}").buildAndExpand(user.getId()).toUri());
return new ResponseEntity<String>(headers, HttpStatus.CREATED);
}
这是json对象我是从UI创建用户操作构建的。
{
"age": 24,
"name": "Amit",
"salary": 15000,
"rank": {
"rank": "Clark"
},
"trainingstatus": {
"trainingStatus": "Completed"
}
}
但这在使用JPA持久化对象时出错。
.MappingJackson2HttpMessageConverter : Failed to evaluate Jackson deserialization for type [simple type, class com.springboot.model.AppUser]
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot handle managed/back reference 'defaultReference': no back reference property found from type [simple type, class com.springboot.model.Rank]
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67) ~[jackson-databind-2.9.3.jar:2.9.3]
at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1451) ~[jackson-databind-2.9.3.jar:2.9.3]
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase._resolveManagedReferenceProperty(BeanDeserializerBase.java:766) ~[jackson-databind-2.9.3.jar:2.9.3]
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.resolve(BeanDeserializerBase.java:474) ~[jackson-databind-2.9.3.jar:2.9.3]
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:293) ~[jackson-databind-2.9.3.jar:2.9.3]
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:244) ~[jackson-databind-2.9.3.jar:2.9.3]
at com.fasterxml.jackson.databind.deser.DeserializerCache.hasValueDeserializerFor(DeserializerCache.java:191) ~[jackson-databind-2.9.3.jar:2.9.3]
at com.fasterxml.jackson.databind.DeserializationContext.hasValueDeserializerFor(DeserializationContext.java:422) ~[jackson-databind-2.9.3.jar:2.9.3]
at com.fasterxml.jackson.databind.ObjectMapper.canDeserialize(ObjectMapper.java:2863) ~[jackson-databind-2.9.3.jar:2.9.3]
答案 0 :(得分:2)
我通过从父类AppUser中删除注释@JsonManagedReference来解决这个问题。只是将@JsonBackReference保留在子类中并添加 在我的其余的getUser和创建的用户操作完美地运行并且为这两个操作返回有效的JSON之后,所有3个类的JsonIdentityInfo注释。
@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")