Я работаю над приложением чата, используя Spring Boot, и столкнулся с проблемой управления сообщениями чата, когда чат достигает максимального размера. Моя цель — реализовать систему, в которой по достижении максимального количества сообщений самое старое сообщение удаляется, чтобы освободить место для нового. Однако я столкнулся с проблемой: новое сообщение заменяет первое сообщение в списке, а не добавляется в конец.
Вот соответствующая часть моего ChatMessageServiceImpl
класса:
@Service
@RequiredArgsConstructor
public class ChatMessageServiceImpl implements ChatMessageService {
private final ChatRepository chatRepository;
private final UserService userService;
@Value("${monopoly.app.chat.max-size}")
private Integer maxSize;
@Override
public ChatMessage save(Chat chat, ChatMessageDto chatMessageDto) {
ChatMessage chatMessage = ChatMessage.builder()
.sender(userService.findByUsername(chatMessageDto.getSender()))
.content(chatMessageDto.getContent())
.timestamp(LocalDateTime.now())
.receiver(chatMessageDto.getReceiver() != null ?
userService.findByUsername(chatMessageDto.getReceiver()) : null)
.chat(chat)
.build();
// Check if the chat has reached the max size
if (chat.getMessages().size() >= maxSize) {
chat.getMessages().remove(0); // Remove the first message
}
chat.getMessages().add(chatMessage); // Add the new message to the end
chatRepository.save(chat);
return chatMessage;
}
}
Когда чат достигнет максимального размера, новое сообщение должно быть добавлено в конец списка, а самое старое сообщение должно быть удалено. Вместо этого создается впечатление, что новое сообщение заменяет первое сообщение в списке.
Вот Chat
класс, если у вас есть вопросы о том, как хранятся сообщения:
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@Builder
@Entity
@Table(name = "chats")
public class Chat {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private Integer unreadMessages = 0;
@OneToMany(mappedBy = "chat", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
private List<ChatMessage> messages = new ArrayList<>();
}
Я подтвердил, что список сообщений является стандартным List
и должен правильно поддерживать операции remove
и add
.
Я попытался явно создать новый список, скопировать сообщения, а затем обновить список сообщений объекта чата:
List<ChatMessage> messages = chat.getMessages();
if (messages.size() >= maxSize) {
messages.remove(0);
}
messages.add(chatMessage);
chat.setMessages(messages);
Chat
новым списком сообщений.Что может быть причиной того, что новое сообщение заменяет первое сообщение, а не добавляется в конец? Есть ли какие-либо потенциальные проблемы с тем, как обрабатывается список или база данных в этой ситуации?
Вы не указываете порядок, поэтому получаете все, что выходит из базы данных. Добавьте @OrderBy("fieldName")
под @OneToMany
в чате:
@OneToMany(mappedBy = "chat", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
@OrderBy("fieldName")
private List<ChatMessage> messages = new ArrayList<>();
Замените fieldName
соответствующим полем, возможно, timestamp
, которое оно имеет на основе кода вашего компоновщика.
Я не знаю причину вашей проблемы. Но вы можете попробовать добавить новое сообщение как:
messages.add(messages.size(), chatMessage);
, тем самым явно добавив новое сообщение в конец коллекции списков.