0

In a application, having a database table CUSTOMERS defined as:

create table CUSTOMERS (
  ID varchar(10),
  CODE varchar(10),
  CID varchar(10),
  SID varchar(10),
  FNAME varchar(50),
  LNAME varchar(50),
  constraint PK_CUSTOMERS primary key (ID, CODE, CID, SID)
);

and the Entity classes are created to populate the data as

@Embeddable
public class CustKey implements Serializable , Cloneable{

    @Transient
    private static final long serialVersionUID = 1L;

    @Column(name = "ID", nullable = false)
    private String id;
    
    @Column(name = "CODE", nullable = false)
    private String code;
    
    @Column(name = "CID", nullable = false)
    private String cid;

    @Column(name = "SID", nullable = false)
    private String sid;
    
    public boolean equals(Object o){
     return id.equals(o.getId()) && ...;
   }

    public int hashcode(){
     return id.hashcode() & ...;
   }
}


@Entity
@Table(name = "CUSTOMERS")
public class CustProfileWrapper implements Serializable,Cloneable  {

    @Transient
    private static final long serialVersionUID = 1L;
    
    @EmbeddedId
    private CustKey custKey;
    
    @Column(name = "FNAME")
    private String fname;
    
    @Column(name = "LNAME")
    private String lname;
}

The records are populated without an issue.

But the Entity classes are move to other project (but keeping the same package name as before) due to some rewrite of the code/project. but on fetching the data by Hibernate Session as

Object object = session.get(CustProfileWrapper.class, custProfileWrapper.getCustKey(), LockMode.NONE);

getting the error

org.hibernate.TypeMismatchException: Provided id of the wrong type for class CustProfileWrapper. Expected: class com.db.CustProfileWrapper, got class com.db.CustProfileWrapper 

However, able to get the record when using the parametrized query as

SQLQuery query = session.createSQLQuery("SELECT * FROM CUSTOMERS WHERE ID = ? "
        + " AND CODE = ? AND CID = ? AND SID = ? ");
query.addEntity(CustProfileWrapper.class);
query.setParameter(0, "101");
...
object = query.list();
        

But it's a low level code when using the query, and we should use the better way like get() method.

Any help/hint will be appreciated!!


Full stack trace of the error: stack trace1 stack trace2 stack trace3 stack trace4

Kishore_2021
  • 645
  • 12
  • 38
  • 1
    My guess is, that you have both classes on the class path but loaded by different class loaders somehow and now Hibernate in fact sees two different class objects. Try debugging to the exception root and determine if the class objects are referring to the same object (same identity hash code) – Christian Beikov Aug 08 '22 at 12:05
  • @ChristianBeikov .. The data population work is over/finished, and can't be debug/run again. Only need to fetch the populated data to show in application. – Kishore_2021 Aug 08 '22 at 13:22
  • UPDATE: Forgot to add equals() and hashcode() methods in CustKey class. – Kishore_2021 Aug 08 '22 at 15:13
  • 1
    Can you share full exception here? – Ashish Patil Aug 09 '22 at 06:36
  • @AshishPatil, pls see the full stack trace in attached images. – Kishore_2021 Aug 09 '22 at 07:06

1 Answers1

0

After so much investigation, found the culprit spring-boot-devtools dependency, as explained here:

I was getting this problem after adding a dependency to spring-boot-devtools in my Springboot project. I removed the dependency and the problem went away. My best guess at this point is that spring-boot-devtools brings in a new classloader and that causes the issue of class casting problems between different classloaders in certain cases where the new classloader is not being used by some threads.

Reference: A dozer map exception related to Spring boot devtools

Refs: ClassCastException when casting to the same class

Kishore_2021
  • 645
  • 12
  • 38