繁体   English   中英

Spring数据映射无法按预期工作

[英]Spring Data mapping doesn't work as expected

我有一个带有两个外键和多对一关联(到表检查点设置 )的表选项db schema

从JPA方面,我有2个双向关联:一侧为Cascade.ALLFetchType.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:由造成无法删除或更新父行,外键约束失败( demooption ,约束FKdhs5wopt13o6b9gl4wydr0l9o外键( setting_id )参考settingid ))在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

此外,在玩耍之后,我发现了一些奇怪的东西,我无法解释:

  1. RewardOption类中为Checkpoint添加@ManyToOne(fetch = FetchType.LAZY) 可解决此问题,但是访类型如何影响级联?
  2. Checkpoint类中的层叠= CascadeType.ALL更改为层叠= CascadeType.REMOVE可以解决此问题,但我需要能够保存层叠...

如果有人可以对这些“修补程序”有所了解,那就太好了。

这是要玩的代码

为了使其正常工作,您需要同步双向关联的两端

这意味着,在调用delete之前,您需要确保将父级与所有子级实体解除关联。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM