补充用户默认酒店唯一约束

This commit is contained in:
andy
2026-07-10 16:19:43 +08:00
parent 8484b44e87
commit 4745e20b9a
5 changed files with 237 additions and 6 deletions

View File

@@ -10,6 +10,7 @@ import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.List;
import java.util.Optional;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Repository;
/**
@@ -75,10 +76,10 @@ public class MybatisPlatformHotelRepository implements PlatformHotelRepository {
@Override
public void ensureUserHotel(Long userId, String hotelId, boolean defaultHotel) {
PlatformUserHotelEntity existing = userHotelMapper.selectOne(Wrappers.<PlatformUserHotelEntity>lambdaQuery()
.eq(PlatformUserHotelEntity::getUserId, userId)
.eq(PlatformUserHotelEntity::getHotelId, hotelId)
.last("LIMIT 1"));
if (defaultHotel) {
clearOtherDefaultHotels(userId, hotelId);
}
PlatformUserHotelEntity existing = findUserHotel(userId, hotelId).orElse(null);
if (existing != null) {
if (defaultHotel && !Boolean.TRUE.equals(existing.getDefaultHotel())) {
existing.setDefaultHotel(true);
@@ -91,7 +92,39 @@ public class MybatisPlatformHotelRepository implements PlatformHotelRepository {
relation.setHotelId(hotelId);
relation.setDefaultHotel(defaultHotel);
relation.setCreatedAt(nowUtc());
userHotelMapper.insert(relation);
try {
userHotelMapper.insert(relation);
} catch (DuplicateKeyException ignored) {
// 多实例并发初始化时唯一索引已经保证授权关系存在,重复插入后只需补齐默认酒店状态。
findUserHotel(userId, hotelId).ifPresent(concurrentExisting -> {
if (defaultHotel && !Boolean.TRUE.equals(concurrentExisting.getDefaultHotel())) {
concurrentExisting.setDefaultHotel(true);
userHotelMapper.updateById(concurrentExisting);
}
});
}
}
/**
* 查询单个用户酒店授权关系,用于写入前检查和并发重复插入后的状态补齐。
*/
private Optional<PlatformUserHotelEntity> findUserHotel(Long userId, String hotelId) {
return Optional.ofNullable(userHotelMapper.selectOne(Wrappers.<PlatformUserHotelEntity>lambdaQuery()
.eq(PlatformUserHotelEntity::getUserId, userId)
.eq(PlatformUserHotelEntity::getHotelId, hotelId)
.last("LIMIT 1")));
}
/**
* 清理同一用户其他默认酒店标记,保证普通用户默认酒店在写入逻辑上保持唯一。
*/
private void clearOtherDefaultHotels(Long userId, String hotelId) {
PlatformUserHotelEntity update = new PlatformUserHotelEntity();
update.setDefaultHotel(false);
userHotelMapper.update(update, Wrappers.<PlatformUserHotelEntity>lambdaUpdate()
.eq(PlatformUserHotelEntity::getUserId, userId)
.ne(PlatformUserHotelEntity::getHotelId, hotelId)
.eq(PlatformUserHotelEntity::getDefaultHotel, true));
}
private LocalDateTime nowUtc() {