Spring数据JPA+;Oracle触发器将ID增加两次

Spring数据JPA+;Oracle触发器将ID增加两次,oracle,hibernate,jpa,spring-data-jpa,database-trigger,Oracle,Hibernate,Jpa,Spring Data Jpa,Database Trigger,我使用以下技术堆栈: spring引导启动器数据jpa 用于连接池的HikariCP 甲骨文数据库 我的实际代码与此类似 /// 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;

我使用以下技术堆栈:

  • spring引导启动器数据jpa
  • 用于连接池的HikariCP
  • 甲骨文数据库
我的实际代码与此类似

   /// 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'
        }
     }
这是我的调查:

当我验证表“FILE”中插入的记录的ID为“58497”时,
repository.save()
返回了一个不同的值。 当我在ID为“58496”的表“ACCESS\u CONTROL\u FILE”上进行第二次插入时,由于ID为“58496”的文件不存在,因此会导致以下错误

原因:java.sql.SQLIntegrityConstraintViolationException:ORA-01400:无法在“DB\u OWNER”“ACCESS\u CONTROL\u FILE”“FILE\u ID”中插入NULL

我不明白为什么
repository.save()
返回的ID(即ID=58496)与数据库中实际插入的ID(ID=58497)不同


我已经调查了互联网上所有与“传播和隔离”相关的选项。

如评论中所述,似乎是数据库触发器导致了这个问题。禁用触发器以让JPA管理ID生成。

看起来序列在数据库级别又增加了一次。你在db检查过你是否有一个触发器或序列在执行它吗?@jusermar10,很好,我没有考虑过。我在我的帖子中添加了这个特殊的触发器。看起来触发器试图为每一行创建一个唯一的主键。你能确认这是否属实吗?是的,这是问题的根源。如果您希望jpa处理序列生成,请禁用触发器我不想出于其他原因完全禁用/删除触发器,我在这里找到了一个替代解决方案,该解决方案基于尚未创建ID的条件抑制触发器。尽管如此,还是要感谢@jusermar10提供的指针。