我们在Java-Spring Boot服务中有一个Kafka使用者,它在多个集群中有多个实例(所有实例都具有相同的使用者组id(。使用者将数据保存到数据库(SQL Server(中。
在保存到数据库之前,代码会检查ItemSet
表中是否存在记录。有效负载中的实际数据保存在子表ItemValue
中,而不是父表ItemSet
中。关系数据表层次结构是按ItemSet
->ItemName
->ItemValue
。ItemSet
表有一个unique constraint
用于部门id、季节组合,以防止多次重复添加。
我需要在捕捉到这个异常后进行一些处理,以确保传入的数据仍然保存在现有的ItemSet
下,不会丢失。我使用的是Spring Data JPA,一旦我发现异常并尝试检索现有记录,我就会得到:
org.hibernate.AssertionFailure:ItemSet条目中的id为null(发生异常后不要刷新会话(。
catch块中的getItemSet()
爆炸。
克服这些比赛条件的最佳方法是什么?
ItemSet savedItemSet = null;
try
{
String seasonName = itemSet.getSeasonName();
Long seasonYear = itemSet.getSeasonYear();
Long departmentId = itemSet.getDepartment().getId();
List<ItemSet> itemSets = attributeSetRepository.findBySeasonNameAndSeasonYearAndDepartmentId(
seasonName, seasonYear, departmentId);
LOGGER.info("Found {} item sets corresponding to season name : {}, season year : {}, "
+ "department id : {}", itemSets.size(), seasonName, seasonYear, departmentId);
if(CollectionUtils.isEmpty(itemSets)) {
savedItemSet = itemSetRepository.save(itemSet);
}
else {
return new CreatedItemSet(itemSets.get(0).getId());
}
}
catch(PersistenceException | DataIntegrityViolationException e)
{
LOGGER.error("An exception occurred while saving itemSet set", e);
if (e.getCause() instanceof ConstraintViolationException)
{
String seasonName = itemSet.getSeasonName();
Long seasonYear = itemSet.getSeasonYear();
Long deptId = itemSet.getDepartment().getId();
LOGGER.info("A duplicate item set found in the database corresponding "
+ "to season name : {}, season year : {} and department : {}",
seasonName, seasonYear, deptId);
ExistingItemSet existingItemSet = getItemSet(seasonName,
seasonYear, deptId);
if(existingItemSet == null) {
LOGGER.info("No item set found");
return null;
}
return new CreatedItemSet(existingItemSet.getId());
}
}
你不能"继续";。事务被标记为回滚,并且在发生约束冲突后,持久性上下文不可用。
您可以通过在持久化/更新之前检查DB是否包含条目来避免约束冲突,也可以在发生约束冲突时在单独的事务中运行其余代码。