Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate n:m extractHashCode throws NullPointerException

I get the following exception while inserting an object with hibernate. Reading from the database works like a charm. I use MySQL 5.5 as database provider and hibernate 3.6.5.

I have the following database schema:

cell(id,cellid,lac,mcc,mnc,insertTime)
location(id,latitude,longitude,altitude,accuracy,heading,hdop,vdop,pdop,insertTime)
cellatlocation(servingCell,neighbourCell,location,signalStrength,insertTime)

where id in cell and location are primary keys and servingCell,neighbourCell and location is the composite primary key in cellatlocation.

java.lang.NullPointerException
at org.hibernate.type.descriptor.java.AbstractTypeDescriptor.extractHashCode(AbstractTypeDescriptor.java:88)
at org.hibernate.type.AbstractStandardBasicType.getHashCode(AbstractStandardBasicType.java:196)
at org.hibernate.type.AbstractStandardBasicType.getHashCode(AbstractStandardBasicType.java:191)
at org.hibernate.type.EntityType.getHashCode(EntityType.java:325)
at org.hibernate.type.ComponentType.getHashCode(ComponentType.java:222)
at org.hibernate.engine.EntityKey.generateHashCode(EntityKey.java:126)
at org.hibernate.engine.EntityKey.<init>(EntityKey.java:70)
at org.hibernate.engine.StatefulPersistenceContext.getDatabaseSnapshot(StatefulPersistenceContext.java:286)
at org.hibernate.engine.ForeignKeys.isTransient(ForeignKeys.java:211)
at org.hibernate.event.def.AbstractSaveEventListener.getEntityState(AbstractSaveEventListener.java:531)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:103)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:685)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:677)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:673)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.hibernate.context.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:345)
at $Proxy17.saveOrUpdate(Unknown Source)

The classes I want to insert: Cell.java

@Entity
@Table(name = "cell", catalog = "crisis")
public class Cell implements Serializable {

private static final long serialVersionUID = -8532796958180260393L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private Integer mnc;
private Integer mcc;
private Long cellid;
private Integer lac;
@org.hibernate.annotations.Type(type = "org.joda.time.contrib.hibernate.PersistentDateTime")
private DateTime insertTime;
@OneToMany(mappedBy = "pk.servingCell")
private List<CellAtLocation> cellAtLocation = new LinkedList<CellAtLocation>();

public Long getId() {
    return id;
}

public void setId(Long id) {
    this.id = id;
}

public Integer getMnc() {
    return mnc;
}

public void setMnc(Integer mnc) {
    this.mnc = mnc;
}

public Integer getMcc() {
    return mcc;
}

public void setMcc(Integer mcc) {
    this.mcc = mcc;
}

public Long getCellid() {
    return cellid;
}

public void setCellid(Long cellid) {
    this.cellid = cellid;
}

public Integer getLac() {
    return lac;
}

public void setLac(Integer lac) {
    this.lac = lac;
}

public DateTime getInsertTime() {
    return insertTime;
}

public void setInsertTime(DateTime insertTime) {
    this.insertTime = insertTime;
}

public List<CellAtLocation> getCellAtLocation() {
    return cellAtLocation;
}

public void setCellAtLocation(List<CellAtLocation> cellAtLocation) {
    this.cellAtLocation = cellAtLocation;
}
}

Location.java

@Entity
@Table(name = "location", catalog = "crisis")
public class Location implements Serializable {

private static final long serialVersionUID = 2197290868029835453L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private Double latitude;
private Double longitude;
private Double altitude;
private Double accuracy;
private Double heading;
private Double hdop;
private Double vdop;
private Double pdop;
@org.hibernate.annotations.Type(type = "org.joda.time.contrib.hibernate.PersistentDateTime")
private DateTime insertTime;

@OneToMany(mappedBy = "pk.location")
private List<CellAtLocation> cellAtLocation = new LinkedList<CellAtLocation>();

public Long getId() {
    return id;
}

public void setId(Long id) {
    this.id = id;
}

public Double getLatitude() {
    return latitude;
}

public void setLatitude(Double latitude) {
    this.latitude = latitude;
}

public Double getLongitude() {
    return longitude;
}

public void setLongitude(Double longitude) {
    this.longitude = longitude;
}

public Double getAltitude() {
    return altitude;
}

public void setAltitude(Double altitude) {
    this.altitude = altitude;
}

public Double getAccuracy() {
    return accuracy;
}

public void setAccuracy(Double accuracy) {
    this.accuracy = accuracy;
}

public Double getHeading() {
    return heading;
}

public void setHeading(Double heading) {
    this.heading = heading;
}

public Double getHdop() {
    return hdop;
}

public void setHdop(Double hdop) {
    this.hdop = hdop;
}

public Double getVdop() {
    return vdop;
}

public void setVdop(Double vdop) {
    this.vdop = vdop;
}

public Double getPdop() {
    return pdop;
}

public void setPdop(Double pdop) {
    this.pdop = pdop;
}

public DateTime getInsertTime() {
    return insertTime;
}

public void setInsertTime(DateTime insertTime) {
    this.insertTime = insertTime;
}

public List<CellAtLocation> getCellAtLocation() {
    return cellAtLocation;
}

public void setCellAtLocation(List<CellAtLocation> cellAtLocation) {
    this.cellAtLocation = cellAtLocation;
}

}

CellAtLocation.java

@Entity
@Table(name = "cellatlocation", catalog = "crisis")
@AssociationOverrides({ @AssociationOverride(name = "pk.servingCell", joinColumns = @JoinColumn(name = "servingCell")),
    @AssociationOverride(name = "pk.neighbourCell", joinColumns = @JoinColumn(name = "neighbourCell")),
    @AssociationOverride(name = "pk.location", joinColumns = @JoinColumn(name = "location")) })

public class CellAtLocation implements Serializable {
private static final long serialVersionUID = -4440795783726362367L;
private CellAtLocationPk pk = new CellAtLocationPk();
private Integer signalStrength;

@EmbeddedId
private CellAtLocationPk getPk() {
    return pk;
}

@SuppressWarnings("unused")
private void setPk(CellAtLocationPk pk) {
    this.pk = pk;
}

@Transient
public Cell getServingCell() {
    return getPk().getServingCell();
}

public void setServingCell(Cell cell) {
    getPk().setServingCell(cell);
}

@Transient
public Cell getNeighbourCell() {
    return getPk().getNeighbourCell();
}

public void setNeighbourCell(Cell cell) {
    getPk().setNeighbourCell(cell);
}

@Transient
public Location getLocation() {
    return getPk().getLocation();
}

public void setLocation(Location location) {
    getPk().setLocation(location);
}

public Integer getSignalStrength() {
    return signalStrength;
}

public void setSignalStrength(Integer signalStrength) {
    this.signalStrength = signalStrength;
}

public boolean equals(Object o) {
    if (this == o)
        return true;
    if (o == null || getClass() != o.getClass())
        return false;
    CellAtLocation that = (CellAtLocation) o;
    if (getPk() != null ? !getPk().equals(that.getPk()) : that.getPk() != null)
        return false;
    return true;
}

public int hashCode() {
    return (getPk() != null ? getPk().hashCode() : 0);
}
}

and finally the primary key mapping itself CellAtLocationPk.java

@Embeddable
public class CellAtLocationPk implements Serializable {
private static final long serialVersionUID = 5286485161491158083L;
private Cell servingCell;
private Cell neighbourCell;
private Location location;

@ManyToOne
public Cell getServingCell() {
    return servingCell;
}

public void setServingCell(Cell servingCell) {
    this.servingCell = servingCell;
}

@ManyToOne
public Cell getNeighbourCell() {
    return neighbourCell;
}

public void setNeighbourCell(Cell neighbourCell) {
    this.neighbourCell = neighbourCell;
}

@ManyToOne
public Location getLocation() {
    return location;
}

public void setLocation(Location location) {
    this.location = location;
}

public boolean equals(Object o) {
    if (this == o)
        return true;
    if (o == null || getClass() != o.getClass())
        return false;
    CellAtLocationPk that = (CellAtLocationPk) o;
    if (servingCell != null ? !servingCell.equals(that.servingCell) : that.servingCell != null)
        return false;
    if (neighbourCell != null ? !neighbourCell.equals(that.neighbourCell) : that.neighbourCell != null)
        return false;
    if (location != null ? !location.equals(that.location) : that.location != null)
        return false;

    return true;
}

public int hashCode() {
    int result;
    result = (servingCell != null ? servingCell.hashCode() : 0);
    result = 31 * result + (neighbourCell != null ? neighbourCell.hashCode() : 0);
    result = 31 * result + (location != null ? location.hashCode() : 0);
    return result;
}
}
like image 268
Florian Avatar asked Jul 19 '11 08:07

Florian


People also ask

Why Null pointer exception occurs?

What Causes NullPointerException. The NullPointerException occurs due to a situation in application code where an uninitialized object is attempted to be accessed or modified. Essentially, this means the object reference does not point anywhere and has a null value.

How to avoid Null pointer exception in java?

To avoid the NullPointerException, we must ensure that all the objects are initialized properly, before you use them. When we declare a reference variable, we must verify that object is not null, before we request a method or a field from the objects.

How to find NullPointerException?

NullPointerException is thrown when a reference variable is accessed (or de-referenced) and is not pointing to any object. This error can be resolved by using a try-catch block or an if-else condition to check if a reference variable is null before dereferencing it.

What is Null pointer exception in java example?

NullPointerException is a runtime exception and it is thrown when the application try to use an object reference which has a null value. For example, using a method on a null reference.


2 Answers

The problem is that hibernate is trying to save the relationship object, CellAtLocation instance, while the children objects, Cell and/or Location instances are not yet persisted. Thus, children objects don't have generated ids associated with them and therefore hibernate can not compute the hash for them.

Before trying to save CellAtLocation instance, try saving the children objects first by calling saveOrUpdate method on them.

like image 61
Alex Avatar answered Oct 31 '22 15:10

Alex


For anyone also dealing with this issue, it occurred in my case simply because I did not have an open and active transaction. The stack trace did not point directly to this being the issue but can be explained as follows:

The parent item was being persisted in the cache and hibernate simply accepted the parent not having an actual ID. If we could have somehow called flush() on our connection we would have then been notified of the non-existent transaction. Instead, when the child item was to be persisted the parent's ID did not TRULY exist. When hibernate went to get the parent's hashed id for the purpose of saving the child, the NPE was thrown.

like image 25
Jonathan Cameron Avatar answered Oct 31 '22 15:10

Jonathan Cameron