我在使用hib插入对象时遇到了以下异常。从数据库阅读数据非常方便。我使用MySQL 5.5作为数据库提供程序,使用hib3.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中的id和location是主键,servingCell、neighborCell和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);
}
}
最后是主键Map自身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;
}
}
5条答案
按热度按时间9nvpjoqh1#
问题是hib试图保存关系对象
CellAtLocation
示例,而子对象Cell
和/或Location
示例尚未持久化,因此,子对象没有关联的generated id
,因此hib无法计算它们的散列。在尝试保存
CellAtLocation
示例之前,请先尝试通过调用saveOrUpdate
方法来保存子对象。qaxu7uf22#
对于任何处理此问题的人,在我的情况下发生此问题只是因为我没有打开和活动的事务。堆栈跟踪没有直接指出这是问题所在,但可以解释如下:
父项被持久化该高速缓存中,而hib只是接受没有实际ID的父项。()的连接上,我们会被告知事务不存在。相反,当子项要被持久化时,父项的ID并不真的存在。当Hibernate为了保存子项而获取父项的哈希ID时,NPE被抛出。
i86rm4rw3#
我遇到了同样的问题,并发现正确Map嵌入式ID的方法是使用@Embeddable、@EmbeddedId和**@MapsId**(问题代码中缺少的一个)。@MapsId注解中的文档提供了一个修复此问题的示例:
示例:
这是解决这个问题的正确方法,这样你就不需要单独保存实体(这不是一个好的做法),相反,hib会通过正确Map生成的id来为你管理整个事务。
希望这对将来有这个问题的人有帮助。
干杯,
fcy6dtqo4#
在我的例子中,发现外键表中的一个主键没有设置,只有实现表中散列码的字段被设置。
mf98qq945#
我也发现问题是hib试图保存关系/父对象,而子对象示例还没有持久化。我通过将子对象Id设置为0来解决这个问题,hib从那里开始,而不必手动保存子对象。希望这能有所帮助。