Вставить в H2, но данные не вставлены - PullRequest
0 голосов
/ 29 апреля 2018

Я уверен, что мне здесь не хватает чего-то действительно глупого очевидного - у меня есть модульный тест для очень простой настройки Slick 3.2. DAO имеет следующие основные методы извлечения и вставки:

  override def questions: Future[Seq[Tables.QuestionRow]] =
    db.run(Question.result)

  override def createQuestion(title: String, body: String, authorUuid: UUID): Future[Long] =
    db.run(Question returning Question.map(_.id) += QuestionRow(0l, UUID.randomUUID().toString, title, body, authorUuid.toString))

И у меня есть несколько модульных тестов - для тестов, которые я использую в памяти H2, и у меня есть скрипт установки (переданный в jdbcurl) для инициализации двух базовых строк в таблице.

Модульные тесты для извлечения работают нормально, и они выбирают две строки, вставленные сценарием инициализации, и я только что добавил простой модульный тест, чтобы создать строку, а затем получить их все - при условии, что он извлечет три строки, но независимо от того, что я делаю, он извлекает только первые два:

  it should "create a new question" in {
    whenReady(questionDao.createQuestion("Question three", "some body", UUID.randomUUID)) { s =>
      whenReady(questionDao.questions(s)) { q =>
        println(s)
        println(q.map(_.title))
        assert(true)
      }
    }
  }

Вывод показывает, что исходный s (возвращающий идентификатор из автоинкена) равен 3, как я и ожидал (я также пробовал вставку, не делая шаг возврата и просто позволяя ей вернуть количество вставленных строк, который возвращает 1 (как expecteD), но, глядя на значения, возвращенные в q, это только первые две строки, вставленные скриптом инициализации.

Чего мне не хватает?

1 Ответ

0 голосов
/ 30 апреля 2018

Я предполагаю, что ваш URL JDBC похож на jdbc:h2:mem:test;INIT=RUNSCRIPT FROM 'init.sql', и пул соединений не используется.

Существует два сценария:

  1. соединение выполняется с keepAliveConnection = true (или путем добавления DB_CLOSE_DELAY=-1 к URL JDBC), а init.sql выглядит примерно так:
DROP TABLE IF EXISTS QUESTION;
CREATE TABLE QUESTION(...);
INSERT INTO QUESTION VALUES(null, ...);
INSERT INTO QUESTION VALUES(null, ...);
  1. соединение выполняется с keepAliveConnection = false (по умолчанию) (без добавления DB_CLOSE_DELAY=-1 к URL JDBC), а init.sql выглядит примерно так:
CREATE TABLE QUESTION(...);
INSERT INTO QUESTION VALUES(null, ...);
INSERT INTO QUESTION VALUES(null, ...);

Вызов questionDao.createQuestion откроет новое соединение с вашей базой данных H2 и запустит скрипт инициализации (init.sql).

В обоих сценариях сразу после этого вызова база данных содержит таблицу QUESTION с 2 строками.

В сценарии (2) после этого вызова соединение закрывается и согласно H2 документации :

По умолчанию закрытие последнего соединения с базой данных закрывает базу данных. Для базы данных в памяти это означает, что содержимое потеряно. Чтобы оставить базу данных открытой, добавьте; DB_CLOSE_DELAY = -1 к URL базы данных. Чтобы сохранить содержимое базы данных в памяти, пока виртуальная машина жива, используйте jdbc: h2: mem: test; DB_CLOSE_DELAY = -1.

Вызов questionDao.questions откроет новое соединение с вашей базой данных H2 и снова вызовет снова сценарий инициализации (init.sql).

В сценарии (1) первое соединение остается активным (а также содержимое базы данных), но новое соединение будет повторно выполнять сценарий инициализации (init.sql), удаляя содержимое базы данных.

Учитывая, что (в обоих сценариях) questionDao.createQuestion возвращает 3, как и ожидалось, но затем содержимое теряется, и поэтому последующий вызов questionDao.questions будет использовать только что инициализированную базу данных.

...