как написать запрос на вставку для таблицы, содержащей столбец ссылки на другую таблицу в play-slick с помощью scala?

Я использую slick 3.1, Play framework 2.5 и scala 2.11. В моем приложении есть таблица «Пользователь» со ссылочным столбцом «addressId», который ссылается на столбец «id» таблицы «Адрес». Я не могу вставить данные в эти обе таблицы. Вот код для этого

Это пользовательская форма:

val registerForm: Form[RegisterForm] = Form {
mapping(
  "id" -> optional(number),
  "firstname" -> nonEmptyText.verifying("letters only", name => name.isEmpty || name.matches("[A-z\\s]+")),
  "lastname" -> nonEmptyText.verifying("letters only", name => name.isEmpty || name.matches("[A-z\\s]+")),
  "email" -> text.verifying(nonEmpty),
  "password" -> text.verifying(nonEmpty),
  "address" -> mapping(
      "id" -> optional(number),
      "city" -> nonEmptyText.verifying("letters only", name => name.isEmpty || name.matches("[A-z\\s]+")),
      "state" -> text,
      "country" -> text,
      "pin" -> number
      )(AddressForm.apply)(AddressForm.unapply)
  )(RegisterForm.apply)(RegisterForm.unapply)
 }

Это два модельных класса:

case class Address(id: Option[Int], city: String, state: String, country: String, pin: Int)
case class User(id: Option[Int], firstname: String, lastname: String, email: String, password: String, addressId: Option[Int])

Вот оба класса сопоставлены с соответствующими таблицами базы данных с запросом таблиц:

private class UserDB(tag: Tag) extends Table[User](tag, "user") {

def id = column[Option[Int]]("id", O.PrimaryKey, O.AutoInc)

def firstname = column[String]("firstname")

def lastname = column[String]("lastname")

def email = column[String]("email")

def password = column[String]("password")

def addressId = column[Option[Int]]("address_id")

override def * = (id, firstname, lastname, email, password, addressId) <> ((User.apply _).tupled, User.unapply)

def address_fk= foreignKey("fk_user_address", addressId, addressTable)(_.id)

 }

private class AddressDB(tag: Tag) extends Table[Address](tag, "address") {

def id = column[Option[Int]]("id", O.PrimaryKey, O.AutoInc)

def city = column[String]("city")

def state = column[String]("state")

def country = column[String]("country")

def pin = column[Int]("pin")

override def * = (id, city, state, country, pin) <> ((Address.apply _).tupled, Address.unapply)

}


private val userTable = TableQuery[UserDB]

private val addressTable = TableQuery[AddressDB]

Скажите, пожалуйста, как я могу вставить данные в обе связанные таблицы одним запросом, используя slick.

Заранее большое спасибо.


person Govardhan    schedule 26.04.2016    source источник


Ответы (1)


Вы должны использовать идентификатор, возвращающий вставку для адреса, и вставку в пользовательскую таблицу в одной транзакции, например:

val query = for {
  adressId <- addressTable returning addressTable.map(_.id) += Address(....)
  userTable += User(..., Some(adressId), ....)
} yield ()

db.run(query.transactionally)

изменить: запрос выше ничего не возвращает, если вам нужно создать пользователя, используйте:

val query = for {
  adressId <- addressTable returning addressTable.map(_.id) += Address(....)
  user <- userTable returning userTable += User(..., Some(adressId), ....)
} yield user

db.run(query.transactionally)
person Hüseyin Zengin    schedule 26.04.2016
comment
Большое спасибо @HüseyinZengin, он работает и решил мою проблему. - person Govardhan; 26.04.2016
comment
Этот запрос возвращает Unit. что, если я хочу, чтобы он возвращал Future[User]? - person Govardhan; 26.04.2016
comment
Большое спасибо @HüseyinZengin. - person Govardhan; 26.04.2016
comment
Пожалуйста, отметьте ответ как правильный, чтобы другие могли получить помощь - person Hüseyin Zengin; 26.04.2016
comment
Извините, приятель, недостаточно репутации, чтобы проголосовать или отметить как полезное. - person Govardhan; 26.04.2016
comment
Но при использовании этого ограничения внешнего ключа запроса в таблице бесполезно. он также работает без какой-либо ссылки между двумя таблицами. Тогда в чем преимущество внешнего ключа? - person Govardhan; 26.04.2016
comment
@Govardhan неважно, во-первых: он работает без внешнего ключа, потому что без внешнего ключа это все еще действительная вставка, во-вторых: с внешним ключом вы не можете вставить случайный Long в этот файл, а также вы можете выбрать, что должно происходить при записи изменены, вы можете увидеть и узнать больше на: slick.typesafe.com/ doc/3.0.0/schemas.html#ограничения - person Hüseyin Zengin; 27.04.2016
comment
Да, понял. Еще раз спасибо @HüseyinZengin. - person Govardhan; 27.04.2016