无法捕获TransactionSystemException

时间:2018-06-11 10:41:23

标签: java spring-boot jpa

我有一个Entity类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 = country,rootBeanClass = class   com.foo.bar.Address,   messageTemplate ='国家应该在那里'}

     

org.springframework.transaction.TransactionSystemException:无法   提交JPA事务;嵌套异常是   javax.persistence.RollbackException:提交时出错   交易

我尝试过使用try / catch块,但仍然无法捕获此异常。

注意:我已经将代码简化到最小程度,如果有遗忘或者我的问题不清楚则请问。

编辑:

完全堆栈stace

  

ERROR ExceptionMapperStandardImpl:39 - HHH000346:托管期间出错   flush [类验证失败   持续时间[com.foo.bar.Address]   for groups [javax.validation.groups.Default,]约束列表   违规行为:     ConstraintViolationImpl {interpolatedMessage ='国家应该在那里',   propertyPath = country,rootBeanClass = class   com.foo.bar.Address,   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)     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at   sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)     在   sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)     在java.lang.reflect.Method.invoke(Method.java:498)at   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)at   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)at   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]   for groups [javax.validation.groups.Default,]约束列表   违规行为:     ConstraintViolationImpl {interpolatedMessage ='国家应该在那里',   propertyPath = transactionId,rootBeanClass = class   com.foo.bar.Address,   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个

2 个答案:

答案 0 :(得分:0)

尝试捕捉PersistenceException。此异常是一个包装异常,不会直接抛出。您可以使用ConstraintViolationException方法提取已包装的getCause()

答案 1 :(得分:-1)

没有捕获ConstraintViolationException的原因是存储库没有抛出该异常,而是抛出TransactionSystemException,它有一个嵌套的ConstraintViolationException实例。

有关捕获嵌套异常的详细信息,请参阅this question