我有一个表选项,该表带有两个外键和多对一关联(到表检查点和设置):{{ 3}}。
从JPA角度来看,我有2个双向关联:一侧是 Cascade.ALL 和 FetchType.EAGER ,另一侧是 Cascade.REMOVE 第二面。这是对应的JPA映射:
@Entity
@Table(name = "checkpoint")
@AllArgsConstructor
@NoArgsConstructor
@Data
public class Checkpoint {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private long location;
@OneToMany(mappedBy = "checkpoint",
cascade = CascadeType.ALL,
orphanRemoval = true,
fetch = FetchType.EAGER)
private List<RewardOption> rewardOptions = new ArrayList<>();
}
@Entity
@Table(name = "setting")
@AllArgsConstructor
@NoArgsConstructor
@Data
public class RewardSetting {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(name = "base_line")
private long baseLine;
@OneToMany(mappedBy = "rewardSetting",
cascade = CascadeType.REMOVE,
orphanRemoval = true)
private List<RewardOption> rewardOptions = new ArrayList<>();
}
@Entity
@Table(name = "option")
@AllArgsConstructor
@NoArgsConstructor
@Data
public class RewardOption {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private long weight;
@ManyToOne
@JoinColumn(name = "setting_id")
private RewardSetting rewardSetting;
@ManyToOne
@JoinColumn(name = "checkpoint_id")
private Checkpoint checkpoint;
}
我也正在使用Spring Data进行实体操作。对我来说,这似乎是一个可行的例子,但是在我练习时却表现出来:
...
rewardSettingRepository.delete(rewardSetting);
或者:
...
rewardSettingRepository.delete(id);
我让JPA尝试从 option 表的 setting 表之前对应的行中删除一行。
有人知道为什么会这样吗? 为什么这种映射会导致这种行为? 如何以正确的方式做事?
完整的堆栈跟踪为:
org.springframework.dao.DataIntegrityViolationException:无法执行语句; SQL [n / a];约束[null];嵌套的异常是org.hibernate.exception.ConstraintViolationException:无法执行语句 在org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:278) 在org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:244) 在org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:521) 在org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:765) 在org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:734) 在org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:518) 在org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:292) 在org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) 在org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 在org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136) 在org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 在org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor $ CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:133)处 在org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 在org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) 在org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 在org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:57) 在org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 在org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) 在com.sun.proxy。$ Proxy82.delete(未知来源) 在com.github.star67.hibernatefetchcascade.HibernateFetchCascadeApplication.testSettingDelete(HibernateFetchCascadeApplication.java:41) 在com.github.star67.hibernatefetchcascade.HibernateFetchCascadeApplication.main(HibernateFetchCascadeApplication.java:36)
由以下原因引起:org.hibernate.exception.ConstraintViolationException:无法执行语句 在org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:59) 在org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42) 在org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:109) 在org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:95) 在org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:207) 在org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:45) 在org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:3261) 在org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:3498) 在org.hibernate.action.internal.EntityDeleteAction.execute(EntityDeleteAction.java:98) 在org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:582) 在org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:456) 在org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:337) 在org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39) 在org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1282) 在org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:465) 在org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:2963) 在org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2339) 在org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:485)处 在org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:147) 在org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access $ 100(JdbcResourceLocalTransactionCoordinatorImpl.java:38) 在org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl $ TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:231)处 在org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:65) 在org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:61) 在org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:517) ...另外18个
由以下原因引起:java.sql.SQLIntegrityConstraintViolationException:无法删除或更新父行:外键约束失败(
demo
。option
,CONSTRAINTFKdhs5wopt13o6b9gl4wydr0l9o
FOREIGN KEY({{1 }})参考文献setting_id
(setting
)) 在com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:115) 在com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:95) 在com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122) 在com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:960) 在com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1116) 在com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1066) 在com.mysql.cj.jdbc.ClientPreparedStatement.executeLargeUpdate(ClientPreparedStatement.java:1396) 在com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdate(ClientPreparedStatement.java:1051) 在sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法)处 在sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 在sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在java.lang.reflect.Method.invoke(Method.java:498) 在org.apache.tomcat.jdbc.pool.StatementFacade $ StatementProxy.invoke(StatementFacade.java:114) com.sun.proxy。$ Proxy89.executeUpdate(未知来源) 在org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:204) ...还有37
此外,在玩耍之后,我发现了一些奇怪的东西,我无法解释:
如果有人可以对这些“修补程序”有所了解,那就太好了。
答案 0 :(得分:0)
要使其正常运行,您需要synchronize both end of the bidirectional association。
这意味着,在调用delete之前,您需要确保将父级与所有子级实体解除关联。