当持久化实体索引超出范围时,SQLServerException异常



我在与另一个实体保持@OneToOne关系的实体时遇到问题。我们最近用Spring 4和Hibernate 4升级到了Java 8,所以我敢肯定有一些注释或配置发生了变化。

相关代码

PermitState.java:

@Entity
@Table(schema = "dbo", name = "PermitState")
public class PermitState implements Serializable {
private String oid;
private Permit permit;
private Integer invoiced;
private Integer used;
private Integer ordered;
private String permitId;

@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "PERMITID")
public Permit getPermit() {
    return permit;
}
@Id
@Column(name = "PERMITID", nullable = true, length = 8,insertable = false,updatable = false)
public String getPermitId() {
    return permitId;
}
... more getters and setters (irrelevant)

Permit.java:

@Entity
@Table(schema = "dbo")
public class Permit {
private String permitid;
private PermitState permitState;

...some more attributes, irrelevant

@Id
@Column(name = "PERMITID", length = 8)
public String getPermitid() {
    return permitid;
}
@OneToOne(mappedBy="permit", cascade=CascadeType.ALL,fetch = FetchType.LAZY)
public PermitState getPermitState() {
    return permitState;
}
异常堆栈

Caused by: org.hibernate.exception.GenericJDBCException: could not insert: [dao.srs.model.PermitState]
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:54)
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:124)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3099)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3521)
    at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:88)
    at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:395)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:387)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:303)
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:349)
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:56)
    at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1195)
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:404)
    at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
    at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:175)
    at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:75)
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:515)
    ... 65 more
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: The index 6 is out of range.
    at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDriverError(SQLServerException.java:171)
    at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.setterGetParam(SQLServerPreparedStatement.java:700)
    at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.setValue(SQLServerPreparedStatement.java:709)
    at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.setString(SQLServerPreparedStatement.java:1034)
    at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.setString(NewProxyPreparedStatement.java:963)
    at org.hibernate.type.descriptor.sql.VarcharTypeDescriptor$1.doBind(VarcharTypeDescriptor.java:57)
    at org.hibernate.type.descriptor.sql.BasicBinder.bind(BasicBinder.java:93)
    at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:284)
    at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:279)
    at org.hibernate.type.ComponentType.nullSafeSet(ComponentType.java:343)
    at org.hibernate.persister.entity.AbstractEntityPersister.dehydrateId(AbstractEntityPersister.java:2835)
    at org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:2804)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3076)
    ... 78 more

可以看到,PermitState实体与Permit有关系(通过PERMITID,它是Permit中的PK),并且有一个名为PERMITID的字段,它应该是连接的Permit的ID。这似乎不工作,虽然,它似乎试图插入所有6个属性,即使允许不应该插入到数据库中。我试图用@Transient在PermitState中注释Permit,但随后我得到一个AnnotationException:

Caused by: org.hibernate.AnnotationException: Unknown mappedBy in: dao.srs.model.Permit.permitState, referenced property unknown: dao.srs.model.PermitState.permit

任何帮助都将非常感激!

只是为了澄清,数据库只有5个字段- OID, PERMITID, INVOICED, USED和ORDERED -这就是为什么我认为它也试图插入Permit实体。当我们使用Java 7、Spring 3、hibernate-annotations 3.3.1时,完全相同的代码无需修改就可以工作。GA和hibernate-entitymanager 3.3.2.GA。我们现在使用Java 8, Spring 4和Hibernate core+entitymanager+ehcache 4.2.19.

在我看来,从例外情况来看,您尝试了@Transient,同时仍然拥有@OneToOne和@JoinColumn。这是没有意义的,因为你告诉Hibernate你想自己处理它,它也应该处理它。

我也发现它有点混乱,你都有许可证实体和PermitState中的permitd。您告诉它您不想更新permitId,但您仍然使用它作为连接列?

我建议删除permitd,在PermitState中只保留Permit实体。如果您愿意,您仍然可以使用getpermitd方法,但将其视为聚合。

如果所有这些都失败了,尝试记录Hibernate生成的SQL,看看发生了什么。也许是贴出来给我们看的

我想我解决了。我仍然不完全确定为什么这工作,但它确实:

我从PermitState.java中删除了PermitId(字符串属性),而使用了PermitState中Permit实体中的PermitId。

它看起来像这样:

Permit.java:

private String permitid;
private PermitState permitState;
@OneToOne(mappedBy="permit", cascade=CascadeType.ALL,fetch = FetchType.LAZY)
public PermitState getPermitState() {
    return permitState;
}

PermitState.java

private Permit permit;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "PERMITID")
public Permit getPermit() {
    return permit;
}

感谢Martin和Bilbo的帮助。

最新更新