JPA/Hibernate:java.sql.SQLException:JDBC调用中的无效参数:参数索引超出范围
问题描述:
我在两个其他表之间使用Hibernate 4时使用了简单的“连接表”。这里是JPA 1.0兼容的实体:JPA/Hibernate:java.sql.SQLException:JDBC调用中的无效参数:参数索引超出范围
@Entity
@Table(name = "Companies")
public class Company
{
@Id
@Column
private Integer id;
@Column
private String name;
...
}
和
@Entity
@Table(name = "PQs")
public class PQ implements Serializable
{
@Id
@Column
private Integer id;
@Column
private String name;
...
}
正如你可以看到两个类似的表,只是一个简单的ID加名。现在互连实体:
@Entity
@Table(name = "Partnerships")
@IdClass(value = PartnershipId.class)
public class Partnership implements Serializable
{
@Id
@Column(name = "pq_id", insertable = false, updatable = false)
private Integer pqId;
@Id
@Column(name = "company_id", insertable = false, updatable = false)
private Integer companyId;
@Column(name = "ordinal_nbr")
private Integer ordinalNbr;
@ManyToOne
@JoinColumn(name = "pq_id", referencedColumnName = "id")
private PQ pq;
@ManyToOne
@JoinColumn(name = "company_id", referencedColumnName = "id")
private Company company;
...
}
注意... , insertable = false, updatable = false
上@Column
这里。
public class PartnershipId implements Serializable
{
private Integer pqId;
private Integer companyId;
public PartnershipId()
{
}
public PartnershipId(Integer pqId, Integer companyId)
{
this.pqId = pqId;
this.companyId = companyId;
}
...
}
当trans.commit();
运行下面的测试代码
public class Main
{
private static String PERSISTENCE_UNIT_NAME = "standalonePu";
private static EntityManagerFactory emf;
private static EntityManager em;
private static EntityTransaction trans;
public static void main(String[] args)
{
setUp(PERSISTENCE_UNIT_NAME);
trans.begin();
PQ detachedPq = new PQ(1, "Test PQ");
Company detachedCompany = new Company(1, "Test Company");
PQ pq = em.merge(detachedPq);
Company company = em.merge(detachedCompany);
Partnership detachedPartnership = new Partnership(1, 1, 1);
detachedPartnership.setPQ(pq);
detachedPartnership.setCompany(company);
Partnership partnership = em.merge(detachedPartnership);
partnership = em.find(Partnership.class, new PartnershipId(1, 1));
System.out.println("Persistent partnership = ("
+ partnership.getPQId() + ", "
+ partnership.getCompanyId() + ", "
+ partnership.getOrdinalNbr() + ")");
trans.commit();
close();
}
private static void setUp(String puName)
{
emf = Persistence.createEntityManagerFactory(puName);
em = emf.createEntityManager();
trans = em.getTransaction();
}
private static void close()
{
em.close();
emf.close();
}
}
... Hibernate的失败,一个很奇怪的例外:
ERROR: Invalid argument in JDBC call: parameter index out of range: 4
Exception in thread "main" javax.persistence.RollbackException: Error while committing the transaction
at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:90)
at main.Main.main(Main.java:44)
Caused by: javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: Invalid argument in JDBC call: parameter index out of range: 4
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1347)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1280)
at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:78)
... 1 more
Caused by: org.hibernate.exception.GenericJDBCException: Invalid argument in JDBC call: parameter index out of range: 4
at org.hibernate.exception.internal.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:148)
at org.hibernate.exception.internal.SQLStateConverter.convert(SQLStateConverter.java:136)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:124)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:109)
at org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:131)
at org.hibernate.engine.jdbc.internal.proxy.AbstractProxyHandler.invoke(AbstractProxyHandler.java:80)
at $Proxy12.setInt(Unknown Source)
at org.hibernate.type.descriptor.sql.IntegerTypeDescriptor$1.doBind(IntegerTypeDescriptor.java:57)
at org.hibernate.type.descriptor.sql.BasicBinder.bind(BasicBinder.java:82)
at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:305)
at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:300)
at org.hibernate.type.ComponentType.nullSafeSet(ComponentType.java:358)
at org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:2599)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2836)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3276)
at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:80)
at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:273)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:265)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:186)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:344)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1084)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:319)
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:100)
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:173)
at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:73)
... 1 more
Caused by: java.sql.SQLException: Invalid argument in JDBC call: parameter index out of range: 4
at org.hsqldb.jdbc.Util.sqlException(Unknown Source)
at org.hsqldb.jdbc.Util.sqlException(Unknown Source)
at org.hsqldb.jdbc.Util.sqlException(Unknown Source)
at org.hsqldb.jdbc.Util.outOfRangeArgument(Unknown Source)
at org.hsqldb.jdbc.JDBCPreparedStatement.checkSetParameterIndex(Unknown Source)
at org.hsqldb.jdbc.JDBCPreparedStatement.setInt(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:124)
... 22 more
Caused by: org.hsqldb.HsqlException: Invalid argument in JDBC call: parameter index out of range: 4
at org.hsqldb.error.Error.error(Unknown Source)
... 31 more
测试的配置中是休眠4.0.0.CR4和HSQLDB 2.0。我也用MySQL 5测试了这个,和非常相似,所以显然Hibernate产生了不正确的代码。
解决此问题的解决方法是将..., insertable = false, updatable = false
放到关系'@JoinColumn
s上,但这不是我真正想要的。
所以,这是一个Hibernate的bug?上面的代码应该是正确的,从JPA的角度...
Hibernate并不真正推荐使用IdClass和Multiple @Id属性。如果使用组件类型表示,这将会更好。 –
你有没有参考你的陈述?以上是普通的JPA 1.0,Hibernate声称自3.5版开始就兼容JPA 2.0。请注意,我想留在这里(JPA)。 – Kawu
http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/#entity-mapping-identifier –