【问题标题】:WrongClassException: Object [id=null] was not of the specified subclassWrongClassException:对象 [id=null] 不属于指定的子类
【发布时间】:2017-10-06 12:28:05
【问题描述】:

我有一个像下面这样的模型:

@Entity(name = "request")
public class VisitRequest {
  @Id
  @GeneratedValue
  private Long id;

  @OneToMany(mappedBy = "visitRequest", cascade = CascadeType.ALL, orphanRemoval = true)
  @JsonManagedReference
  private List<Visitor> visitors;

  //default constructor, getters and setters
}

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "class")
public class Visitor {
  @Id
  @GeneratedValue
  private Long id;

  @ManyToOne
  @JsonBackReference
  private VisitRequest visitRequest;

  //default constructor, getters and setters

}

@Entity
public class ContactPerson extends Visitor {

  private PhoneNumber phoneNumber;

  //default constructor, getters and setters

}

但是当我尝试通过与联系人交换访问者之一来更新 visitRequest,并尝试在 CRUD 存储库上执行该方法时,visitRequestRepository.save(visitRequest);我遇到了这个异常:

Servlet.service() 用于 servlet [dispatcherServlet] 的上下文中的路径 [] 抛出异常 [请求处理失败;嵌套异常是 org.springframework.orm.ObjectRetrievalFailureException:对象 [id=null] 不属于指定的子类 [cern.ais.visits.core.domain.visitor.Visitor] :给定的类 对象与持久副本的类不匹配;嵌套异常是 org.hibernate.WrongClassException:对象 [id=null] 不是 指定子类 [cern.ais.visits.core.domain.visitor.Visitor] : 给定对象的类与持久副本的类不匹配] 根本原因

也许问题是在数据库中contact_person和visitor表中使用了相同的id?

我该如何解决这个问题?我已经搜索了解决方案,但没有一个对我有用。

【问题讨论】:

  • 可能是 persistence.xml 文件中的访问者类的条目丢失或者这可能会有所帮助,stackoverflow.com/questions/31257027/…
  • 我需要在persistence.xml中定义一个Visitor类吗?我这里使用的是注解配置,不是xml配置。
  • 我也遇到了同样的问题,你解决了吗?
  • 负载中的class 属性是什么?另外,@JsonSubtypes 不见了
  • @tomwassing 提出自己的问题并提供minimal reproducible example,您将有更好的机会。

标签: java hibernate jpa


【解决方案1】:

您可能没有在ContactPerson 中初始化visitRequest 引用。请看下面的配置,它适用于 Spring Boot JPA。我使用lombok 生成GetterSetters

这是一个在 Spring Boot https://github.com/ConsciousObserver/SpringBootJpaInheritance 中实现的工作示例

@Data
@Entity(name = "request")
class VisitRequest {
    @Id
    @GeneratedValue
    private Long id;

    @OneToMany(mappedBy = "visitRequest", cascade = CascadeType.ALL, orphanRemoval = true)
    @JsonManagedReference
    private List<Visitor> visitors = new ArrayList<>();
}

@NoArgsConstructor
@Data
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "class")
class Visitor {
    @Id
    @GeneratedValue
    private Long id;

    @ManyToOne
    @JsonBackReference
    private VisitRequest visitRequest;

    public Visitor(VisitRequest visitRequest) {
        this.visitRequest = visitRequest;
    }
}

@NoArgsConstructor
@Data
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
@Entity
class ContactPerson extends Visitor {
    private String phoneNumber;

    public ContactPerson(VisitRequest visitRequest, String phoneNumber) {
        super(visitRequest);
        this.phoneNumber = phoneNumber;
    }
}

【讨论】:

    【解决方案2】:

    我怀疑您遇到此问题的原因是您的注释 @Id and @GeneratedValue 没有被继承。如果您在 ContactPerson 中定义属性 id,您将生成一个 Id,并且不再是问题。

    尝试将 ContactPerson 类更改为:

    @Entity
    public class ContactPerson extends Visitor {
    
      @Id
      @GeneratedValue
      private Long id;
    
      private PhoneNumber phoneNumber;    
      //default constructor, getters and setters
    
    }
    

    【讨论】:

      【解决方案3】:
      @Entity(name = "request")
      public class VisitRequest {
        @Id
        @GeneratedValue
        private Long id;
      
        @OneToMany(mappedBy = "visitRequest", cascade = CascadeType.ALL, orphanRemoval = true)
        @JsonManagedReference
        private List<Visitor> visitors;
      
        //default constructor, getters and setters
      }
      
      @Entity(name = "visitor")
      @Inheritance(strategy = InheritanceType.JOINED)
      @DiscriminatorColumn(name = "visitor_type", discriminatorType = DiscriminatorType.STRING, length = 16)
      @DiscriminatorValue(value = "visitor")
      @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "class")
      public class Visitor {
        @Id
        @GeneratedValue
        private Long id;
      
        @ManyToOne
        @JsonBackReference
        private VisitRequest visitRequest;
      
        //default constructor, getters and setters
      
      }
      
      @Entity(name = "contact_person")
      @Table(name = "contact_person")
      @DiscriminatorValue(value = "contact_person")
      public class ContactPerson extends Visitor {
      
        private PhoneNumber phoneNumber;
      
        //default constructor, getters and setters
      
      }
      

      并且您可以像 contactPersonDao.save(contactPerson) 一样坚持 ContactPerson, 您不能使用访问者链接保留字段。 我不是专家,但它对我有用。 如果他不联系个人,您可以将访客保持为访客

      【讨论】:

        【解决方案4】:

        似乎不同表之间的 id 具有相同的值,因此当 hibernate 尝试加载具有特定 id 的实体时,如果内存中已经存在具有相同 id 的另一个实体,那么 hibernate 会抱怨这个问题。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-08-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-07-24
          • 2012-02-25
          相关资源
          最近更新 更多