changed jdk on 25 springBoot on 3.5.6 and fix code

This commit is contained in:
SlimusMinus
2026-09-30 00:27:10 +03:00
parent 1efb67824f
commit 015b68d96d
19 changed files with 2226 additions and 71 deletions

View File

@@ -0,0 +1,209 @@
databaseChangeLog:
- changeSet:
id: 017-messages-add-chat-id
author: krylov
comment: >
Перевод messages на чаты. Раньше диалоги хранились парами sender_id/receiver_id,
теперь у сообщения есть chat_id. Колонка добавляется nullable, чтобы
существующие строки не сломали миграцию — заполняется следующим changeset.
preConditions:
onFail: MARK_RAN
tableExists:
tableName: messages
not:
columnExists:
tableName: messages
columnName: chat_id
changes:
- addColumn:
tableName: messages
columns:
- column: { name: chat_id, type: BIGINT }
- changeSet:
id: 017-messages-backfill-chats
author: krylov
comment: >
Создаёт чат для каждой уникальной пары собеседников по старым сообщениям
и проставляет chat_id. Данные сохраняются, история не теряется.
preConditions:
onFail: MARK_RAN
tableExists:
tableName: messages
tableExists:
tableName: chats
columnExists:
tableName: messages
columnName: chat_id
changes:
# Сначала чат на каждую пару (user_one_id < user_two_id, как это делает ChatService).
- sql:
splitStatements: false
sql: |
INSERT INTO chats (user_one_id, user_two_id, post_id, created_at)
SELECT p.u1, p.u2, NULL, COALESCE(p.first_at, NOW())
FROM (
SELECT LEAST(m.sender_id, m.receiver_id) AS u1,
GREATEST(m.sender_id, m.receiver_id) AS u2,
MIN(m.created_at) AS first_at
FROM messages m
WHERE m.chat_id IS NULL
AND m.sender_id IS NOT NULL
AND m.receiver_id IS NOT NULL
GROUP BY LEAST(m.sender_id, m.receiver_id), GREATEST(m.sender_id, m.receiver_id)
) p
ON CONFLICT (user_one_id, user_two_id) DO NOTHING
# Затем проставляем каждому сообщению его чат.
- sql:
splitStatements: false
sql: |
UPDATE messages m
SET chat_id = c.id
FROM chats c
WHERE m.chat_id IS NULL
AND c.user_one_id = LEAST(m.sender_id, m.receiver_id)
AND c.user_two_id = GREATEST(m.sender_id, m.receiver_id)
- changeSet:
id: 017-messages-drop-orphans
author: krylov
comment: >
Сообщения, у которых нет чата: chat_id IS NULL (не удалось восстановить
собеседника) либо чат был удалён, а сообщения остались — так было до
появления fk_messages_chat, потому что ON DELETE CASCADE не работал.
Такие сообщения невозможно показать в интерфейсе, они удаляются.
preConditions:
onFail: MARK_RAN
tableExists:
tableName: messages
columnExists:
tableName: messages
columnName: chat_id
changes:
- sql:
splitStatements: false
sql: |
DELETE FROM messages m
WHERE m.chat_id IS NULL
OR NOT EXISTS (SELECT 1 FROM chats c WHERE c.id = m.chat_id)
- changeSet:
id: 017-messages-chat-id-not-null
author: krylov
preConditions:
onFail: MARK_RAN
tableExists:
tableName: messages
columnExists:
tableName: messages
columnName: chat_id
changes:
- addNotNullConstraint:
tableName: messages
columnName: chat_id
columnDataType: BIGINT
- changeSet:
id: 017-messages-fk-chat
author: krylov
comment: >
ON DELETE CASCADE — при удалении чата сообщения удаляются вместе с ним.
Без каскада ChatService.deleteChat падал бы с нарушением FK.
preConditions:
onFail: MARK_RAN
tableExists:
tableName: messages
tableExists:
tableName: chats
not:
foreignKeyConstraintExists:
constraintName: fk_messages_chat
changes:
- addForeignKeyConstraint:
baseTableName: messages
baseColumnNames: chat_id
referencedTableName: chats
referencedColumnNames: id
constraintName: fk_messages_chat
onDelete: CASCADE
- changeSet:
id: 017-messages-idx-chat-created
author: krylov
comment: >
Основные запросы выборки: история чата и счётчик непрочитанных.
preConditions:
onFail: MARK_RAN
tableExists:
tableName: messages
not:
indexExists:
tableName: messages
indexName: idx_messages_chat_created
changes:
- createIndex:
tableName: messages
indexName: idx_messages_chat_created
columns:
- column: { name: chat_id }
- column: { name: created_at }
- changeSet:
id: 017-messages-drop-receiver
author: krylov
comment: >
receiver_id больше не используется: получатель определяется через chats.
Сначала снимаем с него внешний ключ и индекс, иначе dropColumn не пройдёт.
preConditions:
onFail: MARK_RAN
tableExists:
tableName: messages
columnExists:
tableName: messages
columnName: receiver_id
changes:
- dropForeignKeyConstraint:
baseTableName: messages
constraintName: fk_messages_receiver
- dropIndex:
tableName: messages
indexName: idx_messages_users
- dropColumn:
tableName: messages
columnName: receiver_id
- changeSet:
id: 017-messages-not-null
author: krylov
comment: >
Сущность Message объявляет sender_id, content, is_read и created_at как
NOT NULL, но старая схема (004) создала их nullable. Hibernate validate
nullability не проверяет, поэтому расхождение молча оставалось.
preConditions:
onFail: MARK_RAN
tableExists:
tableName: messages
sqlCheck:
expectedResult: 0
sql: >
SELECT COUNT(*) FROM messages
WHERE sender_id IS NULL OR content IS NULL
OR is_read IS NULL OR created_at IS NULL
changes:
- addNotNullConstraint:
tableName: messages
columnName: sender_id
columnDataType: BIGINT
- addNotNullConstraint:
tableName: messages
columnName: content
columnDataType: TEXT
- addNotNullConstraint:
tableName: messages
columnName: is_read
columnDataType: BOOLEAN
- addNotNullConstraint:
tableName: messages
columnName: created_at
columnDataType: TIMESTAMP

View File

@@ -0,0 +1,42 @@
databaseChangeLog:
- changeSet:
id: 018-posts-rules-accepted-type
author: krylov
comment: >
rules_accepted объявлена в changelog 013 как boolean, но Hibernate с
ddl-auto: update успел создать её как varchar — поле в сущности тогда
было String. Теперь сущность использует Boolean, и ddl-auto: validate
падал с "wrong column type". Приводим тип к схеме, приведя значения.
preConditions:
onFail: MARK_RAN
tableExists:
tableName: posts
columnExists:
tableName: posts
columnName: rules_accepted
# Ноль boolean-колонок с таким именем = тип ещё не boolean = changeset нужен.
sqlCheck:
expectedResult: 0
sql: >
SELECT COUNT(*) FROM information_schema.columns
WHERE table_name = 'posts' AND column_name = 'rules_accepted'
AND data_type = 'boolean'
changes:
# В varchar могли попасть мусорные значения — приводим к true/false заранее.
- sql:
splitStatements: false
sql: |
UPDATE posts
SET rules_accepted = CASE
WHEN LOWER(TRIM(rules_accepted)) IN ('true', 't', '1', 'yes', 'y') THEN 'true'
ELSE 'false'
END
- sql:
splitStatements: false
sql: |
ALTER TABLE posts
ALTER COLUMN rules_accepted DROP DEFAULT,
ALTER COLUMN rules_accepted TYPE BOOLEAN USING rules_accepted::boolean,
ALTER COLUMN rules_accepted SET DEFAULT false,
ALTER COLUMN rules_accepted SET NOT NULL

View File

@@ -1,7 +1,15 @@
databaseChangeLog:
- changeSet:
id: 004-create-chats-messages
author: you
id: 014-create-chats
author: krylov
comment: >
Таблица чатов. Раньше создавалась Hibernate (ddl-auto: update),
поэтому changeset идемпотентен: если таблица уже есть — MARK_RAN.
preConditions:
onFail: MARK_RAN
not:
tableExists:
tableName: chats
changes:
- createTable:
tableName: chats
@@ -14,4 +22,43 @@ databaseChangeLog:
- addUniqueConstraint:
tableName: chats
columnNames: user_one_id, user_two_id
constraintName: uq_chat_users
constraintName: uq_chat_users
- changeSet:
id: 014-chats-idx-participants
author: krylov
comment: >
findAllByUserId ищет по (user_one_id = ? OR user_two_id = ?),
без индексов это full scan по всем чатам.
preConditions:
onFail: MARK_RAN
tableExists:
tableName: chats
not:
indexExists:
tableName: chats
indexName: idx_chats_user_one
changes:
- createIndex:
tableName: chats
indexName: idx_chats_user_one
columns:
- column: { name: user_one_id }
- changeSet:
id: 014-chats-idx-participants-two
author: krylov
preConditions:
onFail: MARK_RAN
tableExists:
tableName: chats
not:
indexExists:
tableName: chats
indexName: idx_chats_user_two
changes:
- createIndex:
tableName: chats
indexName: idx_chats_user_two
columns:
- column: { name: user_two_id }

View File

@@ -1,28 +1,12 @@
databaseChangeLog:
- changeSet:
id: 005-drop-old-messages
author: you
changes:
- dropTable:
tableName: messages
cascadeConstraints: true
- changeSet:
id: 006-create-messages-new
author: you
changes:
- createTable:
tableName: messages
columns:
- column: { name: id, type: BIGSERIAL, constraints: { primaryKey: true } }
- column: { name: chat_id, type: BIGINT, constraints: { nullable: false } }
- column: { name: sender_id, type: BIGINT, constraints: { nullable: false } }
- column: { name: content, type: TEXT, constraints: { nullable: false } }
- column: { name: is_read, type: BOOLEAN, defaultValueBoolean: false }
- column: { name: created_at, type: TIMESTAMP, constraints: { nullable: false } }
- addForeignKeyConstraint:
baseTableName: messages
baseColumnNames: chat_id
referencedTableName: chats
referencedColumnNames: id
constraintName: fk_messages_chat
# УСТАРЕЛО. Файл намеренно не подключён в db.changelog-master.yaml.
#
# Раньше здесь был changeSet "005-drop-old-messages", который удалял таблицу
# messages вместе со всеми сообщениями. Подключение этого файла уничтожило бы
# переписку пользователей, поэтому он заменён на безопасную альтернативу.
#
# Актуальная миграция: db/changelog/add/017-messages-chat-id.yaml
# Она добавляет messages.chat_id, создаёт чаты для старых диалогов
# и переносит сообщения, не удаляя данные.
#
# Если чаты уже созданы Hibernate, 017 идемпотентна: preConditions + MARK_RAN.
databaseChangeLog: []

View File

@@ -26,3 +26,6 @@ databaseChangeLog:
- include: { file: db/changelog/alter/013-del-ad_id-click-impression.yaml }
- include: { file: db/changelog/create/011-create-fullscreen-ads.yaml }
- include: { file: db/changelog/constraint/010-idx-post-lat-lng-index.yaml }
- include: { file: db/changelog/create/006-create-chats.yaml }
- include: { file: db/changelog/add/017-messages-chat-id.yaml }
- include: { file: db/changelog/alter/014-posts-rules-accepted-type.yaml }