【问题标题】:Slick 3 - ForeignKeys are not generatedSlick 3 - 不生成外键
【发布时间】:2015-07-27 19:55:14
【问题描述】:

我似乎找不到解决这个奇怪错误的方法:

class Names(tag: Tag) extends Table[Name](tag, "NAME") with Identifiable[Name]{
  def firstName = column[String]("firstName")
  def lastName = column[String]("lastName")
  def profileId = column[Int]("profileId")
  def * = (id.?, firstName, lastName, profileId) <> ((Name.apply _).tupled, Name.unapply)
  def profileFk = foreignKey("profile_fk", profileId, TableQuery[Profiles])(_.id, onDelete=ForeignKeyAction.Cascade)
}

class PhoneNumbers(tag: Tag) extends Table[PhoneNumber](tag, "PHONENUMBER") with Identifiable[PhoneNumber] {
  def number = column[String]("number")
  def kind = column[String]("kind")
  def profileId = column[Int]("profileId")
  def * = (id.?, number, kind, profileId) <> ((PhoneNumber.apply _).tupled, PhoneNumber.unapply)
  def profileFk = foreignKey("profile_fk", profileId, TableQuery[Profiles])(_.id, onDelete=ForeignKeyAction.Cascade)
}

并且配置文件类仅包含一个 id 字段。 Identifiable 提供 id 属性。

我将 Slick 3 与 MySQL 一起使用。

对于 Names,生成 Profiles 的 foreignKey,对于 PhoneNumbers 不生成。为什么?好像没什么区别?

更新:

这里是相关语句:

create table `PHONENUMBER` (`id` INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,`number` TEXT NOT NULL,`kind` TEXT NOT NULL,`profileId` INTEGER NOT NULL)

还有:

alter table `PHONENUMBER` add constraint `profile_fk` foreign key(`profileId`) references `PROFILE`(`id`) on update NO ACTION on delete CASCADE

完整输出:

创建表PROFILE (id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,userId INTEGER NOT NULL)

创建表VERSION (id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,timestamp INTEGER NOT NULL,vector INTEGER NOT NULL)

创建表NAME (id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,firstName TEXT NOT NULL,lastName TEXT NOT NULL,profileId INTEGER NOT NULL,versionId INTEGER NOT NULL)

创建表 PHONENUMBER (id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,number TEXT NOT NULL,kind TEXT NOT NULL,profileId INTEGER NOT NULL,versionId INTEGER NOT NULL)

创建表VIEW (id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY) 创建表PHONENUMBERS_VIEWS (phoneNumber INTEGER NOT NULL,view INTEGER NOT NULL)

创建表CREDENTIALS (id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,username TEXT NOT NULL,password TEXT NOT NULL,userId INTEGER NOT NULL)

创建表USERid INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY)

创建表API_KEY (id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,token TEXT NOT NULL,deviceId TEXT NOT NULL,credentialsId INTEGER NOT NULL)

更新表PROFILE添加约束user_fk外键(userId)引用USER(id)更新时不操作删除不操作

更新表NAME 添加约束profile_fk 外键(profileId) 引用PROFILE(id) 更新NO ACTION on delete CASCADE

更新表NAME添加约束version_fk外键(versionId)引用VERSION(id)更新时不操作删除不操作

更新表PHONENUMBER添加约束profile_fk外键(profileId)引用PROFILEid)更新时删除CASCADE无操作

更新表PHONENUMBER添加约束version_fk外键(versionId)引用VERSION(id)更新时不操作删除不操作

更新表PHONENUMBERS_VIEWS添加约束phoneNumber_fk外键(phoneNumber)引用PHONENUMBER(id)更新时不操作删除时不操作 alter table PHONENUMBERS_VIEWS add constraint view_fk foreign key(view) references VIEW(id) on update NO ACTION on delete NO ACTION

更新表CREDENTIALS添加约束user_fk外键(userId)引用USER(id)更新时不操作删除不操作

更新表API_KEY添加约束credentials_fk外键(credentialsId)引用CREDENTIALS(id)更新时不操作删除不操作

` 符号由于降价而被隐藏,但在原始输出中存在

编辑 2

val profiles = TableQuery[Profiles]
val names = TableQuery[Names]
val phoneNumbers = TableQuery[PhoneNumbers]
val views = TableQuery[Views]
val phoneNumbersToViews = TableQuery[PhoneNumbersToViews]
val users = TableQuery[Users]
val credentials = TableQuery[CredentialsSchema]
val apiKeys = TableQuery[ApiKeys]
val versions = TableQuery[Versions]

val schema = profiles.schema ++
  versions.schema ++
  names.schema ++
  phoneNumbers.schema ++
  views.schema ++
  phoneNumbersToViews.schema ++
  credentials.schema ++
  users.schema ++
  apiKeys.schema

SlickDB().run(DBIO.seq(
  schema.create
))

schema.createStatements.foreach(println)

【问题讨论】:

  • 您是否在生成表后创建了添加的 profileFk ?我会尝试删除表并重新创建。
  • 可以发布您的表创建语句和删除语句吗?如果您解决了这个问题,也请告诉我们。
  • slick.typesafe.com/doc/2.1.0/…。见底部,使用 createstatements 和 dropstatements 并打印生成的 sql。
  • 我将验证的唯一其他原因是您是否使用 myISAM 引擎创建任何表。 myISAM 不支持外键,因此如果语法正确,则在创建外键时不会抛出任何错误。如果不是这样,请将您的 Scala 代码发布到您创建和删除表的位置。
  • 仅供参考,您的创建语句包含两个具有相同名称“profile_fk”的外键约束,但在代码中它们被命名为“profile_fk”和“profileA_fk”

标签: mysql scala persistence slick play-slick


【解决方案1】:

"对于 Names,生成 Profiles 的 foreignKey,对于 PhoneNumbers 则不生成。 为什么?好像没什么区别?”

我认为这里的问题是缺乏差异。

您为Names.profileFkPhoneNumbers.profileFk 使用了相同的外键名称(“profile_fk”)。 MySQL 外键名称必须是唯一的。

我建议将“profile_fk”替换为“name_profile_fk”和“phonenumber_profile_fk”。

但是,您应该会看到一个异常。您包含的第一个 alter table 语句...

alter table NAME add constraint profile_fk foreign key(profileId) references PROFILE(id) on update NO ACTION on delete CASCADE

...应该可以正常运行,但是第二个...

alter table PHONENUMBER add constraint profile_fk foreign key(profileId) references PROFILE(id) on update NO ACTION on delete CASCADE

...是应该有例外的地方。

如果您没有看到异常,则可能是您的应用程序在您执行的未来返回之前终止。您可以通过在 SlickDB().run 命令周围放置 await 来测试它。例如,

import scala.concurrent.Await
import scala.concurrent.duration._
Await.result(
  SlickDB().run(DBIO.seq(schema.create))
  , 10 seconds)

【讨论】:

  • 看来你是完全正确的。现在我得到一个“意外的异常[MySQLIntegrityConstraintViolationException:无法写入;表中的重复键”异常。非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-17
相关资源
最近更新 更多