jpa hibernate invoke save() method with id but perform update?

Viewed 16

I want to update row after inserting in another transaction. The first method is multiInsert(), in that update(TaskRecord taskRecord) method invoked with a new transaction.

What I expect is that:

  1. Begin transaction A.
  2. With transaction A, insert a new record with id: 1.
  3. Begin transaction B.
  4. With transaction B, update id: 1, because transaction A is not committed, so it will wait for lock.(maybe there will lead to deadlock, ignoring it)

What actually perform is that:

  1. Begin transaction A.
  2. insert a new record with id: 1
  3. Begin transaction B.
  4. jpa try to update, but there is a lock in id 1. And jpa perform insert new record again, and database generate a new id: 2.

How can I solve it?

There is the first method.

    @Transactional
    public void multiInsert(){
        TaskRecord taskRecord = new TaskRecord();
        taskRecord.setStatus(TaskStatusEnum.WAIT);
        taskRecord.setName("No.1");
        log.info("now insert: {}", taskRecord);
        // it is normal to perform insert, and it will return entity with id: 1
        taskRecord = taskRecordRepository.save(taskRecord);
        // it will request a new transaction, and change name of entity, and invoke save(). Instead of update the entity with id 1, it inserts row with id 2.
        rollBackTest02.update(taskRecord);
    }

There is the second method.

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void update(TaskRecord taskRecord) {
        log.info("save: {}", taskRecord);
        taskRecord = taskRecordRepository.save(taskRecord);
        log.info("update: {}", taskRecord);
    }

entity

@Entity
@Data
public class TaskRecord {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id", nullable = false)
    private Long id;

    private String name;

    @Enumerated(EnumType.STRING)
    @Column(name = "status", nullable = false)
    private TaskStatusEnum status;
    }

The logs of test method.

2022-09-20 08:59:32.275  INFO 25088 --- [           main] c.c.a.service.RollBackTest01             : now insert: TaskRecord{id=null, name='No.1', status=WAIT}
2022-09-20 08:59:32.332  INFO 25088 --- [           main] c.c.a.service.RollBackTest02             : save: TaskRecord{id=1, name='No.1', status=WAIT}
2022-09-20 08:59:32.365  INFO 25088 --- [           main] c.c.a.service.RollBackTest02             : update: TaskRecord{id=2, name='No.1', status=WAIT}

0 Answers
Related