7

I'm getting a weird error on my application.
I'm trying to retrieve an list of entity from database (MySQL) with session.createCriteria().list() but I'm getting this org.hibernate.WrongClassException.

I have looked up this error and I know what it means, but I don't know how to solve it on my context.

I have the following database structure:

CREATE TABLE vtiger_crmentity (
`crmid` int(19) NOT NULL
)

CREATE TABLE vtiger_account (
    `accountid` int(19) NOT NULL DEFAULT 0
)

CREATE TABLE vtiger_accountscf (
    `accountid` int(19) NOT NULL DEFAULT 0
)

CREATE TABLE vtiger_accoutshipads (
`accountaddressid` int(19) NOT NULL DEFAULT 0
)

CREATE TABLE vtiger_accountbillads (
    `accountaddressid` int(19) NOT NULL DEFAULT 0
)

So, quickly explaining, all the tables are linked by the these id columns, and in the last level, the vtiger_accountscf table has 1 vtiger_accountshipads and 1 vtiger_accountbillads. All the tables have the same PK.
So I made my classes like this (stubs):

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@Table(name = "vtiger_crmentity")
public class VtigerCrmentity {
  @Id
  @Basic(optional = false)
  @Column(name = "crmid", nullable = false)
  public Integer getId() {
    return this.id;

  }
}


@Entity
@PrimaryKeyJoinColumn(name = "accountid")
@Inheritance(strategy = InheritanceType.JOINED)
@Table(name = "vtiger_account")
public class VtigerAccount extends VtigerCrmentity {

}

@Entity
@PrimaryKeyJoinColumn(name = "accountid")
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@Table(name = "vtiger_accountscf")
public class VtigerAccountscf extends VtigerAccount {
}

@Entity
@PrimaryKeyJoinColumn(name = "accountaddressid")
@Table(name = "vtiger_accountbillads")
public class VtigerAccountbillads extends VtigerAccountscf {
}

@Entity
@PrimaryKeyJoinColumn(name = "accountaddressid")
@Table(name = "vtiger_accountshipads")
public class VtigerAccountshipads extends VtigerAccountscf {
}

And here's my problem. When I do:

getSession().createCriteria(VtigerAccountbillads.class).list();

I'm getting the exception:

org.hibernate.WrongClassException: Object with id: 11952 was not of the specified subclass: VtigerAccountbillads (loaded object was of wrong class class VtigerAccountshipads)
    at org.hibernate.loader.Loader.instanceAlreadyLoaded(Loader.java:1391)
    at org.hibernate.loader.Loader.getRow(Loader.java:1344)
    at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:611)
    at org.hibernate.loader.Loader.doQuery(Loader.java:829)
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274)
    at org.hibernate.loader.Loader.doList(Loader.java:2533)
    at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2276)
    at org.hibernate.loader.Loader.list(Loader.java:2271)
    at org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:119)
    at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1716)
    at org.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:347)

By project limitations, I'm not using spring or nothing similar to configure the Hibernate and create the session.

Is my mapping wrong?

Alberson Melo
  • 314
  • 2
  • 3
  • 9
  • `all the tables are linked by the these id columns` -- so you mean to say that all tables have same value for their id? Also can you please clarify what do you mean by `in the last level, the vtiger_accountscf table has 1 vtiger_accountshipads and 1 vtiger_accountbillads.` – Chaitanya Aug 27 '14 at 17:42
  • Yes, the same id across the tables. I meant that the `vtiger_accounts` is joined with `vtiger_accountbillads` and `vtiger_accountshipads` (it's the addresses of the given account) – Alberson Melo Aug 27 '14 at 17:56

3 Answers3

6

Can you tell what data records you have in DB?

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.

Chaitanya
  • 14,187
  • 31
  • 92
  • 131
  • I cannot, but yes, they have the same id. If I map them as separated entities, without extending the parent can I bypass this issue? – Alberson Melo Aug 27 '14 at 17:50
  • Well, not exactly the answer but your insight of the same IDs made me resolve my problem. I removed the `vtiger_accountbillads` and `vtiger_accountshipads` from the inheritance and made them single tables. As I will not edit nor save them directly, this solved my issue. Thank you. – Alberson Melo Aug 27 '14 at 18:53
  • Thanks Alberson for your comments, also I have a question, are you trying to load `VtigerAccountshipads` also when you saw this issue? Because this issue comes ONLY when there are 2 entities with same id in Hibernate's memory. – Chaitanya Aug 27 '14 at 18:55
  • I was trying to load a list of all `VtigerAccountshipads`. A simple `session().createCriteria(VtigerAccountshipads.class).list()`. – Alberson Melo Aug 27 '14 at 19:48
  • The problem was not eliminated. You just changed the model. With the original model, the problem persists. – Alfredo A. Mar 21 '16 at 15:24
0

Additionally to @Chaitanya's answer check when using a persistence.xml that there exists also a mapping for that entity.

Sal
  • 1,190
  • 11
  • 21
0

I ran into the same exception, but for a completely different reason.

We have entities A, B and C. B and C extend A, A is abstract and we used SINGLE_TABLE inheritance.

We also have entities X, Y and Z with the same properties (Y and Z extend X, X is abstract and we used SINGLE_TABLE inheritance).

X has a field of A and is of generic Type A:

public abstract class X<T extends A> {
    @ManyToOne
    T field;
}

Y and Z specify the types of B and C respectively:

@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorValue(value = "Y")
public abstract class Y extends X<B> {
}

We had other classes implement X without specifying a concrete type (keeping < T extends A >) - even when there are no Y or Z in the database (which means Hibernate never has to load any and should actually never create objects Y or Z) we would (sometimes) get a org.hibernate.WrongClassException. Our solution was to remove the concrete types B and C from classes Y and Z and use casts in our code.

Additional note: this seemed to work fine for some years, but popped up after an architectural change where neither hibernate configuration nor any of the classes were changed (we just renamed some packages) and then didn't go away until we removed the concrete generic types.