【发布时间】:2018-11-20 14:15:35
【问题描述】:
我有一个实体类 Person,它通过 JoinColumn 连接到另一个实体 Address 并与 Person 具有 OneToOne 关系,Address 实体在字段 country 上有一个 @NotNull 注释。
简化代码如下:
@Entity
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long PersonId;
@Valid
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
@JoinColumn(name = "address_id")
private Address address;
....
..some more fields, getters and setters etc..
...
}
地址实体如下:
@Entity
public class Address {
@Id
@GeneratedValue
private Long addressId;
private String street;
@NotEmpty(message = "Country should be there")
private String country;
....some more fields and getters and setters etc ....
}
除此之外,我还有一个 PersonRepository。
我还有一个服务方法,即updateAddress,该方法的最简单形式如下:
public class Service {
@Transactional
public void updateAddress(Long personId, Address address) {
try {
Person original = findPersonById(personId);
...some validations etc ....
original.setAddress(address);
personRepository.save(original);
} catch (ConstraintViolationException e) {
}
}
我编写了一个小型单元测试,我尝试使用 updateAddress 方法为没有预定义地址的人更新地址。
即
@Test
void checkUpdateAddress() {
Person person = new Person();
.....initiate some fields, except address ....
Long personId =personRepository.save(person);
Address address = new Address();
address.street("abcd");
service.updatePerson(personId, address);
//assertions etc
}
问题是我得到了
引起:javax.validation.ConstraintViolationException:验证 类 [com.foor.bar.Address] 失败 在组的持续时间内 [javax.validation.groups.Default, ] 约束违规列表:[ ConstraintViolationImpl{interpolatedMessage='国家应该在那里', propertyPath=国家,rootBeanClass=类 com.foo.bar.地址, messageTemplate='国家应该有'}
org.springframework.transaction.TransactionSystemException: 不能 提交 JPA 事务;嵌套异常是 javax.persistence.RollbackException:提交时出错 交易
我尝试过使用 try/catch 块,但仍然无法捕获此异常。
注意:我已将代码简化到最低限度,如果有什么我忘记了或者我的问题不清楚,请询问。
编辑:
全栈
ERROR ExceptionMapperStandardImpl:39 - HHH000346: 托管期间出错 flush [类的验证失败 [com.foo.bar.Address] 在持续时间内 对于组 [javax.validation.groups.Default, ] 约束列表 违规行为:[ ConstraintViolationImpl{interpolatedMessage='国家应该在那里', propertyPath=国家,rootBeanClass=类 com.foo.bar.地址, messageTemplate='国家应该有'} ]]
org.springframework.transaction.TransactionSystemException: 不能 提交 JPA 事务;嵌套异常是 javax.persistence.RollbackException:提交时出错 交易
在 org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:545) 在 org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:746) 在 org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:714) 在 org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:532) 在 org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:304) 在 org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) 在 org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689) 在 com.foo.bar.service.Service$$EnhancerBySpringCGLIB$$57d9106c.updateAddress() 在 com.rfoo.bar.service.MyTest.checkUpdateAddressMethod(MyTest.java:956) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在 java.lang.reflect.Method.invoke(Method.java:498) 在 org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:436) 在 org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:115) 在 org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:170) 在 org.junit.jupiter.engine.execution.ThrowableCollector.execute(ThrowableCollector.java:40) 在 org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:166) 在 org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:113) 在 org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:58) 在 org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$3(HierarchicalTestExecutor.java:112) 在 org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66) 在 org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.executeRecursively(HierarchicalTestExecutor.java:108) 在 org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:79) 在 org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$2(HierarchicalTestExecutor.java:120) 在 java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184) 在 java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175) 在 java.util.Iterator.forEachRemaining(Iterator.java:116) 在 java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801) 在 java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481) 在 java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) 在 java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151) 在 java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174) 在 java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) 在 java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418) 在 org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$3(HierarchicalTestExecutor.java:120) 在 org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66) 在 org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.executeRecursively(HierarchicalTestExecutor.java:108) 在 org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:79) 在 org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$2(HierarchicalTestExecutor.java:120) 在 java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184) 在 java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175) 在 java.util.Iterator.forEachRemaining(Iterator.java:116) 在 java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801) 在 java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481) 在 java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) 在 java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151) 在 java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174) 在 java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) 在 java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418) 在 org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$3(HierarchicalTestExecutor.java:120) 在 org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66) 在 org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.executeRecursively(HierarchicalTestExecutor.java:108) 在 org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:79) 在 org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:55) 在 org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:43) 在 org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:170) 在 org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:154) 在 org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:90) 在 com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:74) 在 com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47) 在 com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242) 在 com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70) 引起:javax.persistence.RollbackException:提交时出错 交易在 org.hibernate.internal.ExceptionConverterImpl.convertCommitException(ExceptionConverterImpl.java:77) 在 org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:71) 在 org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:536) ... 63 更多原因:javax.validation.ConstraintViolationException: 类的验证失败 [com.foo.bar.Address] 在持续时间内 对于组 [javax.validation.groups.Default, ] 约束列表 违规行为:[ ConstraintViolationImpl{interpolatedMessage='国家应该在那里', propertyPath=transactionId, rootBeanClass=class com.foo.bar.地址, messageTemplate='国家应该在那里'}] 在 org.hibernate.cfg.beanvalidation.BeanValidationEventListener.validate(BeanValidationEventListener.java:140) 在 org.hibernate.cfg.beanvalidation.BeanValidationEventListener.onPreInsert(BeanValidationEventListener.java:80) 在 org.hibernate.action.internal.EntityInsertAction.preInsert(EntityInsertAction.java:205) 在 org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:82) 在 org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:600) 在 org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:474) 在 org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:337) 在 org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39) 在 org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1436) 在 org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:493) 在 org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3206) 在 org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2412) 在 org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:473) 在 org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:156) 在 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:68) ... 64 更多
【问题讨论】:
-
你的@Service注解在哪里?没有必要吗?
-
@R.A.Munna 不,没有必要
-
一旦你发现异常你又抛出它......为什么???
-
我的错误,复制/粘贴错误
-
那么当你有一个通用的catch块时,抛出的异常类型是什么?
标签: java spring-boot jpa