Home > Blockchain >  Get method on Spring Repository results in Insert statement
Get method on Spring Repository results in Insert statement

Time:07-13

I'm trying to understand how a "get" method (findXByYAndZAnd...) on a Repository (org.springframework.data.repository.CrudRepository) fails with an ORA-00001 "unique constraint () violated".

Obviously the insert was generated from another (previous) statement, however, I do not understand what's the role of Spring AOP and the CrudMethodMetadataPostProcessor, why the transaction is committed in the middle of it. We do have

dbConfig:
... 
    hikari:
      auto-commit: true 

And

spring:
  application:
    name: xxx
  cache:
    type: caffeine
  jpa:
    database: oracle
    properties:
      hibernate:
        jdbc: 
          batch_size: 200
#          order_inserts: true
#          order_updates: true
#          show_sql: true
        use_sql_comments: false
        format_sql: false

But still... it should either do the transaction immediately, or at the end, isn't it?

ERROR 42664956 --- [task-10] c.e.my-app.service.error.DbLoggerService    : Error saving messages : org.hibernate.exception.ConstraintViolationException: could not execute batch; nested exception is javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not execute batch
RootCause: 
ORA-00001: unique constraint (SIDE.PK_RMESG) violated
Stack Trace: 

org.springframework.orm.jpa.JpaSystemException: org.hibernate.exception.ConstraintViolationException: could not execute batch; nested exception is javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not execute batch
    at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:408) ~[spring-orm-5.2.9.RELEASE.jar!/:5.2.9.RELEASE]
    at org.springframework.orm.jpa.DefaultJpaDialect.translateExceptionIfPossible(DefaultJpaDialect.java:128) ~[spring-orm-5.2.9.RELEASE.jar!/:5.2.9.RELEASE]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:528) ~[spring-orm-5.2.9.RELEASE.jar!/:5.2.9.RELEASE]
    at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61) ~[spring-tx-5.2.9.RELEASE.jar!/:5.2.9.RELEASE]
    at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242) ~[spring-tx-5.2.9.RELEASE.jar!/:5.2.9.RELEASE]
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:154) ~[spring-tx-5.2.9.RELEASE.jar!/:5.2.9.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.9.RELEASE.jar!/:5.2.9.RELEASE]
    at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:149) ~[spring-data-jpa-2.3.4.RELEASE.jar!/:2.3.4.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.9.RELEASE.jar!/:5.2.9.RELEASE]
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95) ~[spring-aop-5.2.9.RELEASE.jar!/:5.2.9.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.9.RELEASE.jar!/:5.2.9.RELEASE]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.2.9.RELEASE.jar!/:5.2.9.RELEASE]
    at com.sun.proxy.$Proxy162.getInstanceByxAndYAndZ(Unknown Source) ~[na:na]
    at com.my-org.my-app.my-component.service.impl.PartServiceImpl.process(PartServiceImpl.java:287) ~[loader-1.0.0-SNAPSHOT.jar!/:1.0.0-SNAPSHOT]

Thanks!

CodePudding user response:

I don't see any sign that a transaction was committed. Since you don't share any code we can only guess but what is probably going on is the following:

You made some changes to some managed entities. This might be by calling save with an entity, or by modifying an entity that you loaded in the same transaction.

These changes don't get flushed to the database immediately, but are delayed as long as possible.

You then perform or trigger some kind of query. This by default configuration of JPA triggers a flush of the changes and therefore the exception.

CrudMethodMetadataPostProcessor.CrudMethodMetadataPopulatingMethodInterceptor doesn't seem to be relevant here. It just gathers some information about the method invoked and then proceeds to the actual implementation (or next aspect) of the method invoked. You can see the invoke method here: https://github.com/spring-projects/spring-data-jpa/blob/b57eb85a230d3a05e45276052ef62b1249e5a0e6/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/support/CrudMethodMetadataPostProcessor.java#L128

As for AOP it is just a mechanic used for get things like CrudMethodMetadataPostProcessor or transaction management and even the implementation of repository methods themselves to be executed. Apart from being crucial for Spring Data itself (remember repositories are just interfaces without normal implementation) it is not really affecting the JPA behaviour described above.

  • Related