7

I have a model like this one below:

@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

}

But when I try to update a visitRequest by exchanging one of the visitors with a contact person, and try to execute the method on a CRUD repository visitRequestRepository.save(visitRequest); I'm getting this exception:

Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.orm.ObjectRetrievalFailureException: Object [id=null] was not of the specified subclass [cern.ais.visits.core.domain.visitor.Visitor] : class of the given object did not match class of persistent copy; nested exception is org.hibernate.WrongClassException: Object [id=null] was not of the specified subclass [cern.ais.visits.core.domain.visitor.Visitor] : class of the given object did not match class of persistent copy] with root cause

Maybe the problem is that in the database there is the same id used in the contact_person and visitor tables?

How can I solve the problem? I've searched for the solutions but none worked for me.

Greg Zuber
  • 1,229
  • 1
  • 12
  • 22
  • May be the entry for class Visitor in persistence.xml file was missing or this may help, http://stackoverflow.com/questions/31257027/org-hibernate-wrongclassexception-on-saving-an-entity-via-hibernate – parlad May 08 '17 at 13:34
  • Do I need to define a Visitor class in persistence.xml? I'm using an annotation configuration here, not an xml one. – Greg Zuber May 08 '17 at 14:41
  • I am having the exact same issue, have you been able to resolve it? – tomwassing Aug 19 '19 at 07:26
  • What is the `class` property in your payload populated with? Also, `@JsonSubtypes` is missing – crizzis Aug 19 '19 at 08:58
  • 3
    @tomwassing you'd have better chances by asking your own question and providing a [mcve]. – Selaron Aug 20 '19 at 07:07
  • @tomwassing Could you provide your code which leads to the issue? On Github or [Pastebin](https://pastebin.com)... – Cepr0 Aug 20 '19 at 12:49
  • why @ManyToOne don't have join column? https://en.wikibooks.org/wiki/Java_Persistence/ManyToOne – Huy Nguyen Aug 22 '19 at 10:21

4 Answers4

0

You're probably not initializing visitRequest reference in ContactPerson. Please take a look at the following configuration, it works with Spring Boot JPA. I have used lombok to generate Getter and Setters.

Here's a working example implemented in 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;
    }
}
11thdimension
  • 10,333
  • 4
  • 33
  • 71
0

I suspect the reason you are having this issue is your annotations @Id and @GeneratedValue are not inherited. If you define property id in ContactPerson you will have a generated Id and will not be a problem anymore.

Try changing ContactPerson class to:

@Entity
public class ContactPerson extends Visitor {

  @Id
  @GeneratedValue
  private Long id;

  private PhoneNumber phoneNumber;    
  //default constructor, getters and setters

}
YoManTaMero
  • 391
  • 4
  • 10
0
@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

}

And you able to persist ContactPerson like contactPersonDao.save(contactPerson), you can`t persist field with visitor link. I am not expert but it work for me. And you can persist visitor as visitor if he not contactPerson

0

It seems the id's between different tables has same value, so when hibernate is trying to load an entity with a specific id and if another entity with same id is already present in memory then hibernate is complaining about this issue.

Mouad Chaouki
  • 538
  • 4
  • 6