【发布时间】:2025-11-26 10:05:01
【问题描述】:
我有两个实体和一个服务。没有 @Transactional 一切正常(回滚除外)。现在我在服务方法中添加了一个@Transactional,使其成为事务并在错误时自动回滚。但是现在使用这种方法的所有测试都失败了javax.persistence.EntityNotFoundException: Unable to find org.kitodo.mediaserver.core.db.entities.Work with id xyz(xyz 是我的工作项的 ID)。
然后我尝试将cascade = {CascadeType.PERSIST, CascadeType.MERGE} 添加到 ActionData 实体的工作字段中。比我在与以前相同的位置上得到另一个例外:org.h2.jdbc.JdbcSQLException: Concurrent update in table "WORK": another transaction has updated or deleted the same row [90131-196]
我假设出于某种原因它会尝试同时使用两个转换。
这是什么原因,我该如何做?
实体
@Entity
public class Work {
private String id;
private String title;
private String path;
private String hostId;
private Instant indexTime;
private Set<Collection> collections;
private String allowedNetwork = "global";
protected Work() {}
public Work(String id, String title) {
this.id = id;
this.title = title;
}
@Id
public String getId() {
return id;
}
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "work_collection",
joinColumns = @JoinColumn(name = "work_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "collection_name", referencedColumnName = "name"))
public Set<Collection> getCollections() {
return collections;
}
// getters/setters
}
@Entity
public class ActionData {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@ElementCollection
@CollectionTable(name = "action_parameter")
private Map<String, String> parameter = new HashMap<>();
@ManyToOne
@JoinColumn(name = "work_id", referencedColumnName = "id", nullable = false)
private Work work;
private String actionName;
private Instant requestTime;
private Instant startTime;
private Instant endTime;
private ActionData() {}
public ActionData(Work work, String actionName, Map<String, String> parameter) {
this.work = work;
this.parameter = parameter;
this.actionName = actionName;
}
// getters/setters
}
服务方法
@Service
public class ActionService {
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
public Object performRequested(ActionData actionData) throws Exception {
// some checks
actionData.setStartTime(Instant.now());
// !!! javax.persistence.EntityNotFoundException: Unable to find org.kitodo.mediaserver.core.db.entities.Work with id xyz
actionRepository.save(actionData);
IAction actionInstance = getActionInstance(actionData.getActionName());
Object result;
result = actionInstance.perform(actionData.getWork(), actionData.getParameter());
actionData.setEndTime(Instant.now());
actionRepository.save(actionData);
return result;
}
}
测试
@Test
public void performRequestedAction() throws Exception {
// given
init();
work1 = entityManager.persist(work1);
actionData1 = new ActionData(work1, "mockAction", parameter1);
actionData1.setRequestTime(Instant.now());
actionData1 = entityManager.persist(actionData1);
entityManager.flush();
// when
Object action = actionService.performRequested(actionData1);
// then
assertThat(action).isNotNull();
assertThat(action).isInstanceOf(String.class);
assertThat(action).isEqualTo("performed");
assertThat(actionData1.getStartTime()).isBetween(Instant.now().minusSeconds(2), Instant.now());
assertThat(actionData1.getEndTime()).isBetween(Instant.now().minusSeconds(2), Instant.now());
}
【问题讨论】:
标签: java spring hibernate spring-boot transactions