Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate could not deserialize error

Tags:

java

hibernate

I have this Oracle table:

SQL>  Name                                         Null?    Type
 ----------------------------------------- -------- ----------------------------
 JOB_ID                                    NOT NULL VARCHAR2(13)
 TYPE                                      NOT NULL NUMBER
 COMPONENT_DESCRIPTION                     NOT NULL VARCHAR2(255)
 COMPONENT_ID                                       VARCHAR2(13)
 STATUS                                    NOT NULL NUMBER(1)
 REASON                                             VARCHAR2(255)
 NOTES                                              VARCHAR2(255)

SQL>

There is no defined primary key but JOB_ID, TYPE and COMPONENT_DESCRIPTION combined are unique. I cannot make any changes to the database structure and the code I'm working will only ever read from the DB, it will never write to it.

I have made this Hibernate map file:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
    "classpath://org/hibernate/hibernate-mapping-3.0.dtd">
<hibernate-mapping schema="ARCHIVE">

<class name="myclass.ArchiveJobHeaderComponents" table="JOB_HEADER_COMPONENTS">
    <composite-id>
        <key-property name="jobId" column="JOB_ID" type="java.lang.String" />
        <key-property name="type" column="TYPE" type="java.lang.Number" />
        <key-property name="componentDescription" column="COMPONENT_DESCRIPTION" type="java.lang.String" />
    </composite-id>
    <property name="componentId" column="COMPONENT_ID" type="java.lang.String" not-null="false" />
    <property name="status" column="STATUS" type="java.lang.Number" />
    <property name="reason" column="REASON" type="java.lang.String" not-null="false" />
    <property name="notes" column="NOTES" type="java.lang.String" not-null="false" />
</class>

<query name="JobHeaderComponents.lookupJobHeaderComponents">
    <![CDATA[from myclass.ArchiveJobHeaderComponents where
               jobId = :jobId and
               type = :type and
               componentDescription = :componentDescription ]]>
</query>

<query name="JobHeaderComponents.listJobHeaderComponentsByComponentId">
    <![CDATA[from myclass.ArchiveJobHeaderComponents where componentId = :id]]>
</query>

</hibernate-mapping>

This is the corresponding Java class file:

package myclass;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;

import java.io.Serializable;
import java.lang.Number;
import java.util.HashSet;

public class ArchiveJobHeaderComponents implements Serializable {

    private String jobId;
    private Number type;
    private String componentDescription;
    private String componentId;
    private Number status;
    private String reason;
    private String notes;

    public String getJobId() {
        return jobId;
    }

    public void setJobId(String jobId) {
        this.jobId = jobId;
    }

    public Number getType() {
        return type;
    }

    public void setType(Number type) {
        this.type = type;
    }

    public String getComponentDescription() {
        return componentDescription;
    }

    public void setComponentDescription(String componentDescription) {
        this.componentDescription = componentDescription;
    }

    public String getComponentId() {
        return componentId;
    }

    public void setComponentId(String componentId) {
        this.componentId = componentId;
    }

    public Number getStatus() {
        return status;
    }

    public void setStatus(Number status) {
        this.status = status;
    }

    public String getReason() {
        return reason;
    }

    public void setReason(String reason) {
        this.reason = reason;
    }

    public String getNotes() {
        return notes;
    }

    public void setNotes(String notes) {
        this.notes = notes;
    }

    public int hashCode() {
       return new HashCodeBuilder().
                           append(getJobId()).
                           append(getType()).
                           append(getComponentDescription()).
                           append(getComponentId()).
                           append(getStatus()).
                           append(getReason()).
                           append(getNotes()).toHashCode();
    }

    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (!(o instanceof ArchiveJobHeaderComponents)) {
            return false;
        }
        ArchiveJobHeaderComponents that = (ArchiveJobHeaderComponents) o;
        return new EqualsBuilder().append(this.getJobId(), that.getJobId()).
                           append(this.getType(), that.getType()).
                           append(this.getComponentDescription(), that.getComponentDescription()).
                           append(this.getComponentId(), that.getComponentId()).
                           append(this.getStatus(), that.getStatus()).
                           append(this.getReason(), that.getReason()).
                           append(this.getNotes(), that.getNotes()).isEquals();
    }

    public String toString() {
        return new ToStringBuilder(this).
                           append("jobId", getJobId()).
                           append("type", getType()).
                           append("componentDescription", getComponentDescription()).
                           append("componentId", getComponentId()).
                           append("status", getStatus()).
                           append("reason", getReason()).
                           append("notes", getNotes()).toString();
    }

}

Whenever I get data back from a query, I get 'Could not deserialize' followed by an 'EOFException' error.

I've checked:
- There are no variables in the Java class of type serialize
- The Java class is implementing Serializable

I don't want to split the three columns (JOB_ID, TYPE and COMPONENT_DESCRIPTION) into a separate 'Id' class as I'm having conceptual problems with how the data is accessed. (I realize this is not recommended but is supported).

Can anyone point out what I've done wrong with how I've implemented this?

Thanks

EDIT:
I've changed the hbm.xml to not have a composite key, just an id on JOB_ID with no improvement.
I've added not-null="false" to the columns that can be empty, also no improvement.

like image 881
user1174838 Avatar asked Dec 29 '13 03:12

user1174838


1 Answers

Actually, having a look over the code and the Hibernate mapping file, I believe that the problem is that you are trying to map columns TYPE and STATUS to a Number. Number is an abstract class, so cannot be instantiated directly.

As both TYPE and STATUS are NOT NULL, I'd use primitive Java types to store their values, eg:

public class ArchiveJobHeaderComponents implements Serializable {

  private String jobId;
  private int type; // int should give you a large enough range - but change to long if required
  private String componentDescription;
  private String componentId;
  private boolean status; // status appears to be a boolean (NUMBER(1))
  private String reason;
  private String notes;
  // remainder omitted
}

Also, please remember to update the Hibernate mapping file to reflect the above!!

like image 63
Muel Avatar answered Oct 10 '22 13:10

Muel