Heroku PostgreSQL: перезагрузка добавляет дубликаты строк - PullRequest
0 голосов
/ 27 октября 2019

У меня есть приложение весенней загрузки, работающее на Heroku с дополнением PostgreSQL. После запуска Spring Boot автоматически создает фиктивные данные в PostgreSQL, такие как users и их контактная информация . Таблицы и операторы вставки хранятся в Schema.sql (pastebin) и Data.sql (pastebin)

При первом запуске все работает нормально, но после перезапускаПриложение Spring boot снова создает те же строки, что приводит к ошибке, связанной с дублированием строк, дублированием отношений и т. д.

Как отключить восстановление данных при перезапуске?

Heroku Конфигурационные переменные установлены на:

enter image description here

Каждый оператор вставки SQL имеет ON CONFLICT DO NOTHING и каждый оператор создания таблицыимеет ЕСЛИ НЕ СУЩЕСТВУЕТ

Ответы [ 2 ]

2 голосов
/ 28 октября 2019

Хотя @richyen правильно определил проблему, я бы предложил другое решение: исправьте вашу схему и используйте естественные ключи для своих пользователей вместо (или, по крайней мере, в дополнение к) суррогатный serial ключ .

CREATE TABLE IF NOT EXISTS users(
  id SERIAL PRIMARY KEY,
  username varchar(255) UNIQUE NOT NULL,
--                      ^^^^^^
  email varchar(255) UNIQUE NOT NULL,
--                   ^^^^^^
  PASSWORD varchar(255) NOT NULL,
  enabled INTEGER DEFAULT 0,
  created_at TIMESTAMP,
  modified_at TIMESTAMP,
  removed_at TIMESTAMP
);

(A PRIMARY KEY точно такой же, как UNIQUE NOT NULL, за исключением того, что вы можете иметь его только один раз, и он станет значением по умолчаниюдля ссылок внешнего ключа на таблицу, которые явно не указывают столбец).

Это приведет к ожидаемым конфликтам при попытке вставить пользователей с одинаковыми именами или адресами электронной почты.

1 голос
/ 28 октября 2019

Проблема в том, что, даже если вы укажете ON CONFLICT DO NOTHING, вы не укажете столбец id в своих операторах INSERT. Это не обязательно плохо, но в основном сводит на нет ваше предложение ON CONFLICT DO NOTHING (по крайней мере, ради последовательности запуска). Вы никогда не столкнетесь с конфликтом, потому что столбец id является последовательным и является вашим основным ключом. Поэтому, если вы явно не назовете его в своем операторе INSERT, база данных с радостью добавит еще одну строку со значением «next» этой последовательности id вместе с другими столбцами, указанными в вашем INSERT. Конфликт возникает только тогда, когда вы сталкиваетесь с ситуацией, когда у вас есть два идентичных значения для первичного ключа, и в вашем Data.sql вы никогда не достигнете этой ситуации.

Если вы действительно хотите поведение ON CONFLICT DO NOTHING, затем вам нужно добавить столбец id в ваши INSERT s, а затем обязательно установить ваши последовательности с setval(), чтобы новые строки, сгенерированные вашим приложением, не были случайно удалены или проигнорированы из-за id конфликт.

Другой вариант (если ваш набор данных предназначен ТОЛЬКО для разработки) - урезать таблицы, чтобы каждый раз получать чистый рабочий набор данных (но это зависит от ваших требований). Если вы сделаете это, то вам также нужно будет сбросить свои последовательности, чтобы ваши id не только продолжали расти вечно.

Наконец, вы можете просто установить SPRING_DATASOURCE_INITIALIZATION_MODE = Never теперь, когда вы загрузилиначальные данные. Опять же, это просто решение, которое вам нужно принять на основе ваших требований.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...