[英]Spring Data mapping doesn't work as expected
我有一个带有两个外键和多对一关联(到表检查点和设置 )的表选项 : db schema 。
从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尝试从选项表中的相应行之前删除设置表中的行。
有谁知道为什么它会这样运作? 为什么这种映射会导致这种行为? 如何以正确的方式做?
完整的堆栈跟踪为:
org.springframework.dao.DataIntegrityViolationException:无法执行语句; SQL [n / a]; 约束[null]; 嵌套的异常是org.hibernate.exception.ConstraintViolationException:无法在org.springframework.orm.jpa.vendors.HibernateJlateDate处的org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:278)处执行语句。 (HibernateJpaDialect.java:244)在org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:521)在org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:765)在org.springframework。 org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:518)上的transaction.support.AbstractPlatformTransactionManager.java:734)在org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction( 292)在org.springframework.transac org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)上的tion.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)在org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java: 136)at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor $ CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostwork atjava。 org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)上的.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)在org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation。 :179),网址为org.springframework.data.repository.core.support.Surrou org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)的ndingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:57)在org.springframework.aop.framework.JdkDynamicAopProxy.com上的org.springframework.aop.framework.JdkDynamicAopProxy.com com.github.star67.hibernatefetchcascade.HibernateFetchCascadeApplication.testSettingDelete(HibernateFetchCascadeApplication.java:41)上的.sun.proxy。$ Proxy82.delete(未知源),com.github.star67.hibernatefetchcascade.HibernateFetchCascadeApplication.main(HibernateFetchCascadeApplication36。 )
引起原因:org.hibernate.exception.ConstraintViolationException:无法在org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java)的org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:59)处执行语句:42)在org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:109)在org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:95)在org.hibernate。 org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:45)处的engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:207)在org.hibernate.persister.entity.AbstractEntityPersister。在org.hibernate.org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:3498)处org.hibernate.action.internal.EntityDeleteAction.execute(EntityDeleteAction.java:98)处delete(AbstractEntityPersister.java:3261) .engine.sp i.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.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。 org.hibernate.resource.org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:147)处的beforeTransactionCompletion(JdbcCoordinatorImpl.java:485) nsaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access $ 100(JdbcResourceLocalTransactionCoordinatorImpl.java:38)at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl $ Transaction。 org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:61)上的.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:65)org.springframework.orm.jpa.Jpa.JpaTransactionManager.doCommit(JpaTransactionManager .java:517)...还有18个
java.sql.SQLIntegrityConstraintViolationException:由造成无法删除或更新父行,外键约束失败(
demo
。option
,约束FKdhs5wopt13o6b9gl4wydr0l9o
外键(setting_id
)参考setting
(id
))在com.mysql.cj.jdbc.exceptions com.mysql.cj.jdbc.exceptions上的.SQLError.createSQLException(SQLError.java:115)。com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java上的.SQLError.createSQLException(SQLError.java:95) :com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:960)处com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1116)处com.mysql.cj.jdbc。在com.mysql.cj.jdbc.ClientPreparedStatement.executeLargeUpdate(ClientPreparedStatement.java:1396)处的ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1066)在com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdate(ClientPreparedStatementjava: .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
此外,在玩耍之后,我发现了一些奇怪的东西,我无法解释:
如果有人可以对这些“修补程序”有所了解,那就太好了。
为了使其正常工作,您需要同步双向关联的两端 。
这意味着,在调用delete之前,您需要确保将父级与所有子级实体解除关联。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.