1

I use the following tech stack:

  • spring-boot-starter-data-jpa
  • HikariCP for connection pooling
  • Oracle DB

My actual code looks similar to this.

   /// My trigger looks like this
   CREATE OR REPLACE TRIGGER FILE_BRI
     BEFORE INSERT
     ON FILE
     FOR EACH ROW
     BEGIN
       SELECT FILE_SEQ.NEXTVAL INTO :NEW.ID FROM DUAL;
     END;
   ///

   public class FILE implements Serializable {
          @Id
        @SequenceGenerator(
                name = "FILE_SEQ",
                sequenceName = "FILE_SEQ",
                allocationSize = 1)
        @GeneratedValue(
                strategy = GenerationType.SEQUENCE,
                generator = "FILE_SEQ"
        )
        private long id;
    }

    public class ServiceA () {

        @Transactional(propagation = REQUIRES_NEW, isolation = READ_COMMITTED) 
        public File insertFile() {
         // Below line returns the inserted File object with ID as '58496'
           return fileRepository.save(file)
        }

        @Transactional(propagation = REQUIRES_NEW, isolation = READ_COMMITTED) 
        public AccessControl insertAccessControl() {
        // Below line results in 'SQLIntegrityConstraintViolationException' (full error at the bottom of this post)
            return accessControlRepository.save(accessControlFile)
         }
     }

     Public class FileProcessor() {
       ServiceA serviceA;
       public void someMethod() {
         // insert the file and get the inserted record
           File insertedFile = serviceA.insertFile(file);

         // get the ID from the inserted file and make another insert into another table
           serviceA.insertAccessControl(insertedFile.getId()); // inserted file ID is '58496'
        }
     }

This is my investigation:

When I verified the ID of the inserted record in the table "FILE" is '58497', however repository.save() returned a different value. When I make the second insert on table "ACCESS_CONTROL_FILE" with FILE_ID as '58496' it results in the error below because the FILE with ID as '58496' does not exist.

Caused by: java.sql.SQLIntegrityConstraintViolationException: ORA-01400: cannot insert NULL into ("DB_OWNER"."ACCESS_CONTROL_FILE"."FILE_ID")

I'm puzzled as to why would repository.save() return a different ID(i.e. ID=58496) than what is actually inserted(ID=58497) in the database!

I've investigated all options that I could find on the internet related to 'Propagation and Isolation'.

ssasi
  • 1,758
  • 1
  • 12
  • 18
  • 1
    Looks like the sequence is incremented at database level one more time. Did you check at db whether you have a trigger or sequence which is doing it? – Ram Dec 13 '18 at 15:59
  • @jusermar10, good one, I did not think about it. I'm adding that particular trigger to my post. It looks like the trigger tries to create a unique primary key for each row. Could you confirm if it is indeed true or not? – ssasi Dec 13 '18 at 16:16
  • Yes it is causing the issue. Please disable the trigger if you want jpa to take care of sequence generation – Ram Dec 13 '18 at 17:07
  • 1
    I do not want to disable/remove the trigger entirely for some other reason and I found an alternative solution here https://stackoverflow.com/a/8003294/4262073 which suppress the trigger based on the condition that an ID is NOT already created. Nevertheless, thanks @jusermar10 for the pointer. – ssasi Dec 14 '18 at 10:53

1 Answers1

2

As mentioned in comments, Looks like a database trigger is causing the issue. Disable the trigger to let JPA to manage the ID generation.

Ram
  • 1,743
  • 2
  • 18
  • 40