Spring Boot JPA 错误:无法处理托管/反向引用“defaultReference”:从类型中找不到反向引用属性

Posted

技术标签:

【中文标题】Spring Boot JPA 错误:无法处理托管/反向引用“defaultReference”:从类型中找不到反向引用属性【英文标题】:Spring boot JPA error : Cannot handle managed/back reference 'defaultReference': no back reference property found from type 【发布时间】:2018-10-08 06:01:11 【问题描述】:

我有以下 3 个域模型对象,其中 appuser 的排名和培训状态如下。获取调用在返回 JSON 对象的情况下工作正常,但在 JPA 中添加模型对象时出现错误。

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]

【问题讨论】:

你能提供你的模型结构吗? 嗨@Novy,您现在可以检查一下吗?对您有很大帮助吗? 我已经在 Github 中添加了我的测试项目:github.com/harshalpatil2012/Springboot 【参考方案1】:

我已经通过从我的父类 AppUser 中删除注释 @JsonManagedReference 解决了这个问题。只是将@JsonBackReference 保留在子类中并添加 之后所有 3 个类的 JsonIdentityInfo 注释我的休息 getUser 和创建用户操作完美运行,并且它为这两个操作返回有效的 JSON。

 @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")

【讨论】:

以上是关于Spring Boot JPA 错误:无法处理托管/反向引用“defaultReference”:从类型中找不到反向引用属性的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot - Mysql Driver - JPA - 在服务器运行发布请求很长时间后显示无法打开 JPA EntityManager 进行事务处理

java - 如何在spring boot java中编写一个函数来处理JPA存储库中的自定义查询?

无法将 Spring Data MongoDB + Spring Data JPA 与 Spring Boot 一起使用

无法访问托管在 EBS 上的 Spring Boot 应用程序

我无法使用 Spring Boot 和 JPA 连接到 mysql 数据库

Spring Boot JPA多对多关系-Rest Web Service无法返回子对象