在使用hibernate模式插入对象时,出现以下异常。从数据库读取就像一个魅力。我使用 MySQL 5.5 作为数据库提供程序,并使用 hibernate3.6.5 。
我有以下数据库架构:
cell(id,cellid,lac,mcc,mnc,insertTime) location(id,latitude,longitude,altitude,accuracy,heading,hdop,vdop,pdop,insertTime) cellatlocation(servingCell,neighbourCell,location,signalStrength,insertTime)
其中cell和location中的id是主键,而serveCell,neighbourCell和location是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)
我要插入的类: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); } }
最后是主键映射本身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; } }
问题在于,hibernate状态正在尝试保存关系对象(CellAtLocation例如实例),而子对象Cell和/或Location实例尚未持久化。因此,子对象没有generated id与之关联的对象,因此hibernate无法为其计算哈希值。
CellAtLocation
Cell
Location
generated id
在尝试保存CellAtLocation实例之前,请先尝试通过在子对象上调用saveOrUpdate方法来保存子对象。
saveOrUpdate