我在映射三个 JPA 实体之间的关系时遇到问题。首先,我向您展示所涉及的数据库表:
西利斯塔
idciclista (PK)
(其他领域...)普鲁巴
idprueba (PK)
(其他领域...)铭文
idcclista (PK, FK in Ciclista.idciclista)
idprueba (PK, FK in Prueba.idprueba, FK in Variante.idprueba)
idvariante (FK in Variante.idvariante)
(其余字段...)变体
idprueba (PK, FK in Prueba.idprueba)
idvariante (PK)
(其余字段...)
问题在于突出显示的字段,它同时是 Inscripcion 的复合 PK、Prueba 中的 FK 和 Variante 中的复合 FK 的一部分。
我的 JPA 实体:
@Entity
@Table(name = "inscripcion")
@IdClass(value=InscripcionPK.class)
public class Inscripcion {
// ATTRIBUTES
@Column
private int dorsal;
@Column
@Temporal(TemporalType.TIMESTAMP)
private Date fechaHora;
@Column
private int estado;
// RELATIONSHIPS
@Id
@ManyToOne
@JoinColumn(name = "idciclista")
private Ciclista participante;
@Id
@ManyToOne
@JoinColumn(name = "idprueba", insertable=false, updatable=false)
private Prueba prueba;
@ManyToOne
@JoinColumns({
@JoinColumn(name="idprueba"),
@JoinColumn(name="idvariante")
})
private Variante variante;
//Constructors, public getters and setters...
}
@Embeddable
public class InscripcionPK implements Serializable {
private static final long serialVersionUID = -582735882125091352L;
int participante;
int prueba;
//Public getters and setters, hashcode, equals...
}
我不粘贴其余的映射,因为到目前为止它们没有给我造成任何问题,但它们也引用了当前实体(双向映射)。
持久化“Inscripcion”对象时出现以下异常:
...
Caused by: javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: Parameter index out of range (7 > number of parameters, which is 6).
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1377)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1300)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1306)
at org.hibernate.ejb.AbstractEntityManagerImpl$CallbackExceptionMapperImpl.mapManagedFlushFailure(AbstractEntityManagerImpl.java:1500)
at org.hibernate.engine.transaction.synchronization.internal.SynchronizationCallbackCoordinatorImpl.beforeCompletion(SynchronizationCallbackCoordinatorImpl.java:109)
at org.hibernate.engine.transaction.synchronization.internal.RegisteredSynchronization.beforeCompletion(RegisteredSynchronization.java:53)
at com.sun.enterprise.transaction.JavaEETransactionImpl.commit(JavaEETransactionImpl.java:435)
... 90 more
Caused by: org.hibernate.exception.GenericJDBCException: Parameter index out of range (7 > number of parameters, which is 6).
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:54)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:110)
at org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:129)
at org.hibernate.engine.jdbc.internal.proxy.AbstractProxyHandler.invoke(AbstractProxyHandler.java:81)
at sun.proxy.$Proxy211.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:92)
at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:280)
at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:275)
at org.hibernate.type.ComponentType.nullSafeSet(ComponentType.java:358)
at org.hibernate.persister.entity.AbstractEntityPersister.dehydrateId(AbstractEntityPersister.java:2784)
at org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:2753)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3025)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3469)
at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:88)
at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:362)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:354)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:275)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:326)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:52)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1213)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:402)
at org.hibernate.engine.transaction.synchronization.internal.SynchronizationCallbackCoordinatorImpl.beforeCompletion(SynchronizationCallbackCoordinatorImpl.java:104)
... 92 more
Caused by: java.sql.SQLException: Parameter index out of range (7 > number of parameters, which is 6).
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1074)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:988)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:974)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:919)
at com.mysql.jdbc.PreparedStatement.checkBounds(PreparedStatement.java:3813)
at com.mysql.jdbc.PreparedStatement.setInternal(PreparedStatement.java:3795)
at com.mysql.jdbc.PreparedStatement.setInternal(PreparedStatement.java:3840)
at com.mysql.jdbc.PreparedStatement.setInt(PreparedStatement.java:3784)
at com.mysql.jdbc.jdbc2.optional.PreparedStatementWrapper.setInt(PreparedStatementWrapper.java:399)
at com.sun.gjc.spi.base.PreparedStatementWrapper.setInt(PreparedStatementWrapper.java:190)
at sun.reflect.GeneratedMethodAccessor82.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:616)
at org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:122)
如果我将“insertable = false,updatable = false”放在“variante”的@JoinColum's 中,我会得到以下异常:
...
Caused by: javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`projectbike`.`inscripcion`, CONSTRAINT `fk_inscripcion_variante1` FOREIGN KEY (`idvariante`, `idprueba`) REFERENCES `variante` (`idvariante`, `idprueba`) ON DELETE NO ACTION ON UPDATE NO ACTI)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1377)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1300)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1306)
at org.hibernate.ejb.AbstractEntityManagerImpl$CallbackExceptionMapperImpl.mapManagedFlushFailure(AbstractEntityManagerImpl.java:1500)
at org.hibernate.engine.transaction.synchronization.internal.SynchronizationCallbackCoordinatorImpl.beforeCompletion(SynchronizationCallbackCoordinatorImpl.java:109)
at org.hibernate.engine.transaction.synchronization.internal.RegisteredSynchronization.beforeCompletion(RegisteredSynchronization.java:53)
at com.sun.enterprise.transaction.JavaEETransactionImpl.commit(JavaEETransactionImpl.java:435)
... 90 more
Caused by: org.hibernate.exception.ConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`projectbike`.`inscripcion`, CONSTRAINT `fk_inscripcion_variante1` FOREIGN KEY (`idvariante`, `idprueba`) REFERENCES `variante` (`idvariante`, `idprueba`) ON DELETE NO ACTION ON UPDATE NO ACTI)
at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:74)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:110)
at org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:129)
at org.hibernate.engine.jdbc.internal.proxy.AbstractProxyHandler.invoke(AbstractProxyHandler.java:81)
at sun.proxy.$Proxy233.executeUpdate(Unknown Source)
at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:56)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3028)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3469)
at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:88)
at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:362)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:354)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:275)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:326)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:52)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1213)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:402)
at org.hibernate.engine.transaction.synchronization.internal.SynchronizationCallbackCoordinatorImpl.beforeCompletion(SynchronizationCallbackCoordinatorImpl.java:104)
... 92 more
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`projectbike`.`inscripcion`, CONSTRAINT `fk_inscripcion_variante1` FOREIGN KEY (`idvariante`, `idprueba`) REFERENCES `variante` (`idvariante`, `idprueba`) ON DELETE NO ACTION ON UPDATE NO ACTI)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:532)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
at com.mysql.jdbc.Util.getInstance(Util.java:386)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1040)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4096)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4028)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2490)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2651)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2734)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2155)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2458)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2375)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2359)
at com.mysql.jdbc.jdbc2.optional.PreparedStatementWrapper.executeUpdate(PreparedStatementWrapper.java:875)
at com.sun.gjc.spi.base.PreparedStatementWrapper.executeUpdate(PreparedStatementWrapper.java:125)
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:616)
at org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:122)
... 106 more
我不知道这是否是 Hibernate 错误,是否 JPA 不支持这种情况,或者我是否遗漏了一些明显的东西。
编辑:
我还发布了我的Variante
课程,因为它也有一个复合键。我希望它有帮助:
@Entity
@Table(name="variante")
@IdClass(value=VariantePK.class)
public class Variante {
//ATRIBUTOS
@Id
@Column(name="idvariante")
private short id;
@Column
private String nombre;
@Column
private Integer longitud;
@Column
private Integer desnivelPos;
@Column
private boolean mostrarTrack;
//RELACIONES
@Id
@ManyToOne(optional = false, cascade=CascadeType.ALL)
@JoinColumn(name="idprueba")
private Prueba prueba;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name="idrecorrido")
private Recorrido recorrido;
@OneToMany(mappedBy = "variante", cascade = CascadeType.ALL, fetch=FetchType.EAGER)
private Set<Inscripcion> inscripciones;
// Consructors, getters and setters...
}
public class VariantePK implements Serializable {
private static final long serialVersionUID = -3276237020478540672L;
private short id;
private Integer prueba;
public VariantePK() {
super();
}
//Constructors, getters, setters, hashcode, equals...
}