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:
- Begin transaction A.
- With transaction A, insert a new record with id: 1.
- Begin transaction B.
- 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:
- Begin transaction A.
- insert a new record with id: 1
- Begin transaction B.
- 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}