Новое сообщение чата заменяет первое сообщение, а не добавляется в конец

Я работаю над приложением чата, используя 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 новым списком сообщений.

Что может быть причиной того, что новое сообщение заменяет первое сообщение, а не добавляется в конец? Есть ли какие-либо потенциальные проблемы с тем, как обрабатывается список или база данных в этой ситуации?

Я не знаю причину вашей проблемы. Но вы можете попробовать добавить новое сообщение как: messages.add(messages.size(), chatMessage);, тем самым явно добавив новое сообщение в конец коллекции списков.

prasad_ 20.08.2024 06:00
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
1
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы не указываете порядок, поэтому получаете все, что выходит из базы данных. Добавьте @OrderBy("fieldName") под @OneToMany в чате:

@OneToMany(mappedBy = "chat", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
@OrderBy("fieldName")
private List<ChatMessage> messages = new ArrayList<>();

Замените fieldName соответствующим полем, возможно, timestamp, которое оно имеет на основе кода вашего компоновщика.

Другие вопросы по теме