Java 持久化实体时SQLServerException-索引超出范围

Java 持久化实体时SQLServerException-索引超出范围,java,spring,hibernate,jpa,orm,Java,Spring,Hibernate,Jpa,Orm,我无法将一个实体与另一个实体保持@OneToOne关系。我们最近用Spring4和Hibernate4升级到了Java8,所以我确信有一些注释或配置发生了变化 相关代码 Caused by: org.hibernate.exception.GenericJDBCException: could not insert: [dao.srs.model.PermitState] at org.hibernate.exception.internal.StandardSQLExceptionCo

我无法将一个实体与另一个实体保持@OneToOne关系。我们最近用Spring4和Hibernate4升级到了Java8,所以我确信有一些注释或配置发生了变化

相关代码

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.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;
}
private String permitid;
private PermitState permitState;

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

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的字段,该字段应该是连接的许可证的ID。但这似乎不起作用,它似乎试图插入所有6个属性,即使不应该将Permit插入数据库。我试图在PermitState中用@Transient注释Permit,但随后得到一个AnnotationException:

Caused by: org.hibernate.AnnotationException: Unknown mappedBy in: dao.srs.model.Permit.permitState, referenced property unknown: dao.srs.model.PermitState.permit
任何帮助都将不胜感激

更新
只是澄清一下,DB只有5个字段-OID、PERMITID、发票、使用和订购-这就是为什么我认为它也尝试插入许可实体的原因。当我们使用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中的Permit实体和permitId。您告诉它您不想更新permitId,但仍将其用作联接列

我建议删除permitId,并且只将许可证实体设置为PermitState。如果愿意,您仍然可以使用getPermitId方法,但可以将其视为agregate


如果所有其他操作都失败,请尝试记录Hibernate生成的SQL以查看发生了什么。也许是贴出来让我们看看。

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

我从PermitState.java中删除了PermitId(字符串属性),而是在PermitState中使用了PermitId

看起来是这样的:

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;
}
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的帮助。

还有一件事我发现PERMITID在两个地方被用作列名。在permitState中作为PERMITID,也用于映射。不,DB只有5个字段,因为Permit不应该被持久化。应仅持久化从Permit.PermitId派生的PermitId。此外,在Java/Spring/Hibernate升级之前,该代码工作正常。当您在Permit上指定@OneTONE(mappedBy)时,Permit作为对象不会持久化到您的案例PermitState中,这是一种双向关系,因此它将在PermitState表中创建使用Permit映射的FK。现在,您指定@JoinColumn的问题是什么,然后名称是PERMITID,并且在@ID和@Column上名称是PERMITID,谢谢您的回复。我同意同时拥有Permit和PermitId看起来很奇怪(维护旧代码可能非常令人沮丧……)。我试图删除PermitId,但许可证实体仅位于PermitState中。但是,我无法更改数据库,因此我仍然需要将PermitId(许可证实体的PK)保存在PermitState中。这里有一个简单的UML图,显示了我对它的设想。关于如何实现这一点有什么帮助吗?我使用permitState.java中permitState属性上的@OneToOne(mappedBy=“permit”)和permitState.java中permitState属性上的@OneToOne,@JoinColumn(name=“PERMITID”)解决了这个问题。见下面我的答案。谢谢你的帮助!