我正在使用带有PostgreSQL数据库的Hibernate 3.6。我使用@IdClass与复合键映射了一对多关系。当我在拥有实体上调用SaveOrUpdate时,当hibernate尝试插入子关系时,我收到异常。
例外是:
org.postgresql.util.PSQLException: The column index is out of range: 4, number of columns: 3.
at org.postgresql.core.v3.SimpleParameterList.bind(SimpleParameterList.java:56)
at org.postgresql.core.v3.SimpleParameterList.setNull(SimpleParameterList.java:141)
at org.postgresql.jdbc2.AbstractJdbc2Statement.setNull(AbstractJdbc2Statement.java:1215)
at org.postgresql.jdbc3.AbstractJdbc3Statement.setNull(AbstractJdbc3Statement.java:1490)
at org.postgresql.jdbc4.AbstractJdbc4Statement.setNull(AbstractJdbc4Statement.java:84)
at com.zaxxer.hikari.proxy.PreparedStatementJavassistProxy.setNull(PreparedStatementJavassistProxy.java)
at org.hibernate.type.descriptor.sql.BasicBinder.bind(BasicBinder.java:78)
at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:283)
at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:278)
at org.hibernate.type.ComponentType.nullSafeSet(ComponentType.java:317)
at org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:2195)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2431)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2875)
at org.hibernate.action.EntityInsertAction.execute(EntityInsertAction.java:79)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:273)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:265)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:184)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:383)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:133)
...
失败的实体看起来像这样(它包括在@IdClass中注释的类):
@Entity
@IdClass(DsbRowDataDashboard.RowDataDashboardPK.class)
@Table(name = "dsb_row_data_dashboard")
public class DsbRowDataDashboard implements Serializable {
private static final long serialVersionUID = 2036988934943807608L;
public static final String NQ_GetRowsInvolvedForWorkstreamMoveUp = "DsbRowDataDashboard.getRowsInvolvedForWorkstreamMoveUp";
public static final String NQ_GetRowsInvolvedForWorkstreamMoveDown = "DsbRowDataDashboard.getRowsInvolvedForWorkstreamMoveDown";
public static final String NQ_GetRowsInvolvedForSubtaskMoveUp = "DsbRowDataDashboard.getRowsInvolvedForSubtaskMoveUp";
public static final String NQ_GetRowsInvolvedForSubtaskMoveDown = "DsbRowDataDashboard.getRowsInvolvedForSubtaskMoveDown";
public static final String NQ_FindMaxPositionForWorkstream = "DsbRowDataDashboard.findMaxPositionForWorkstream";
public static final String NQ_FindMaxPositionForSubtask = "DsbRowDataDashboard.findMaxPositionForSubtask";
@Id
@Column(name = "row_data_id", insertable = false, updatable = false)
private Long rowDataId;
@Id
@Column(name = "dashboard_id", insertable = false, updatable = false)
private Long dashboardId;
@Column(name = "row_position")
private Long position;
@ManyToOne// DO NOT cascade anything here
@JoinColumn(name = "row_data_id")
private DsbRowData rowData;
@ManyToOne // DO NOT cascade anything here
@JoinColumn(name = "dashboard_id")
private DsbDashboard dashboard;
public DsbRowDataDashboard() {
}
public DsbRowDataDashboard(DsbRowData rowData, DsbDashboard dsbDashboard, Long position) {
this.rowData = rowData;
this.dashboard = dsbDashboard;
this.position = position;
}
public Long getRowDataId() {
return rowDataId;
}
public void setRowDataId(Long rowDataId) {
this.rowDataId = rowDataId;
}
public Long getDashboardId() {
return dashboardId;
}
public void setDashboardId(Long dashboardId) {
this.dashboardId = dashboardId;
}
public Long getPosition() {
return position;
}
public void setPosition(Long position) {
this.position = position;
}
public DsbRowData getRowData() {
return rowData;
}
public void setRowData(DsbRowData rowData) {
this.rowData = rowData;
}
public DsbDashboard getDashboard() {
return dashboard;
}
public void setDashboard(DsbDashboard dashboard) {
this.dashboard = dashboard;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((rowDataId == null) ? 0 : rowDataId.hashCode());
result = prime * result + ((dashboardId == null) ? 0 : dashboardId.hashCode());
result = prime * result + ((position == null) ? 0 : position.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof DsbRowDataDashboard))
return false;
DsbRowDataDashboard other = (DsbRowDataDashboard) obj;
if (rowDataId == null) {
if (other.rowDataId != null)
return false;
} else if (!rowDataId.equals(other.rowDataId))
return false;
if (dashboardId == null) {
if (other.dashboardId != null)
return false;
} else if (!dashboardId.equals(other.dashboardId))
return false;
if (position == null) {
if (other.position != null)
return false;
} else if (!position.equals(other.position))
return false;
return true;
}
@Override
public String toString() {
return "DsbRowDashboard [rowDataid=" + rowDataId + ", dashboardId = " + dashboardId + "position=" + position + "]";
}
public static class RowDataDashboardPK implements Serializable {
private static final long serialVersionUID = -1665119146485718132L;
protected Long rowDataId;
protected Long dashboardId;
public RowDataDashboardPK() {
}
public RowDataDashboardPK(Long rowDataId, Long dashboardId) {
this.rowDataId = rowDataId;
this.dashboardId = dashboardId;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((rowDataId == null) ? 0 : rowDataId.hashCode());
result = prime * result + ((dashboardId == null) ? 0 : dashboardId.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof RowDataDashboardPK))
return false;
RowDataDashboardPK other = (RowDataDashboardPK) obj;
if (rowDataId == null) {
if (other.rowDataId != null)
return false;
} else if (!rowDataId.equals(other.rowDataId))
return false;
if (dashboardId == null) {
if (other.dashboardId != null)
return false;
} else if (!dashboardId.equals(other.dashboardId))
return false;
return true;
}
}
}
父母的关系如下:
@OneToMany(fetch = FetchType.LAZY, mappedBy = "rowData", orphanRemoval = true)
@Cascade({CascadeType.ALL})
private Set<DsbRowDataDashboard> rowPositions = new HashSet<DsbRowDataDashboard>(0);
我已经启用了hibernate的所有相关调试来查看sql和debug。这就是导致失败的原因:
[DEBUG] [ org.hibernate.SQL:] [ 111] -
/* insert com.myapp.model.DsbRowDataDashboard
*/ insert
into
dsb_row_data_dashboard
(dashboard_id, row_position, row_data_id)
values
(?, ?, ?)
[TRACE] [ org.hibernate.type.descriptor.sql.BasicBinder:] [ 82] - binding parameter [1] as [BIGINT] - 1392
[TRACE] [ org.hibernate.type.descriptor.sql.BasicBinder:] [ 82] - binding parameter [2] as [BIGINT] - 0
[TRACE] [ org.hibernate.type.descriptor.sql.BasicBinder:] [ 82] - binding parameter [3] as [BIGINT] - 50
[TRACE] [ org.hibernate.type.descriptor.sql.BasicBinder:] [ 70] - binding parameter [4] as [BIGINT] - <null>
[DEBUG] [ org.hibernate.jdbc.AbstractBatcher:] [ 418] - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
之前的sql是插入的父行,它是成功的。然后hibernate尝试插入子进程并失败。整个交易将被回滚。
我设置关系的两边,然后调用hibernate saveorupdate:
DsbRowDataDashboard rowDataDashboard = new DsbRowDataDashboard(rowData, rowData.getDsbDashboard(), maxpos);
rowData.getRowPositions().add(rowDataDashboard);
dsbRowDataDao.update(rowData);
-----
public T update(T obj) {
getSessionFactory().getCurrentSession().saveOrUpdate(obj);
return obj;
}
我已经看到了另外两个问题几乎完全相同的问题,但没有真正的解决方案。
这是一个非常接近同一问题的问题:
https://stackoverflow.com/questions/37092382/spring-data-jpa-column-index-out-of-range
非常感谢任何见解。
谢谢。