database - Scala-Slick 中外键的类型投影

标签 database scala slick

我正在使用 Scala,并且是 Play 和 Slick 的新手。我开始屏蔽一个简单的数据库结构,我不确定处理外键和投影的正确方法。在页面底部的示例中,它目前无法编译,因为无法直接提升 ForeignKey,所以将查询结果提升为我的类型的正确方法是什么(基本上是没有方法和其他构造函数):

case class UserCompanyPermission(pk: UUID, company: Company, user: User, accessLevel: CompanyPermissionLevel)

要么我想让类型投影返回一个 UserCompanyPermission,要么有一种方法来包装所有进出 DAO 方法的东西,所以从外面我只是将我的 Scala 类型传入。基本上我想确保我的业务逻辑与状态完全分离以使其更易于测试,因此能够将所有表细节限制在这个存储包中。是他们的包装方式,还是我在 DAO 对象中编写的每个方法都需要自己进行转换?

trait CompaniesComponent { this: UsersComponent =>
  val Companies: Companies
  val UserCompanyPermissions: UserCompanyPermissions

  implicit val companyPermissionLevelTypeMapper = MappedTypeMapper.base[CompanyPermissionLevel.Value, Int](
    { level => level.id }, { id => CompanyPermissionLevel(id) }
  )

  class Companies extends Table[Company]("Company") {
    def pk = column[UUID]("pk", O.PrimaryKey)
    def subdomain = column[String]("subdomain", O.NotNull)
    def name = column[String]("name", O.NotNull)

    def * = pk ~ subdomain ~ name <> (Company.apply _, Company.unapply _)
  }


  class UserCompanyPermissions extends Table[UserCompanyPermission]("UserCompanyPermission") {

    def pk = column[UUID]("pk", O.PrimaryKey)
    def company_pk = column[UUID]("company_pk", O.NotNull)
    def user_pk = column[UUID]("user_pk", O.NotNull)
    def accessLevel = column[CompanyPermissionLevel.Value]("access_level", O.NotNull)

    def company = foreignKey("company_pk", company_pk, Companies)(_.pk)
    def user = foreignKey("user_pk", user_pk, Users)(_.pk)

    def * = pk ~ company ~ user ~ accessLevel <> (UserCompanyPermission.apply _, UserCompanyPermission.unapply _)
  }

}


object Companies extends DAO {
  def insert(company: Company)(implicit session: Session) {
    Companies.insert(company)
  }
}

object UserCompanyPermissions extends DAO {
  def insert(perm: UserCompanyPermission)(implicit session: Session) {
    UserCompanyPermissions.insert(perm)
  }
}

最佳答案

使用 Slick 的推荐方法是永远不要嵌套保存行值的案例类。它们应该只包含实际的列,而不是任何相关的对象,因为那样会硬编码它们必须一起加载(除非你在幕后做了一些神奇的延迟加载,这使得使用和实现变得复杂)。相反,您编写查询,使用元组关联您现在需要的特定数据的值。

// FYI
case class UserCompanyPermission( pk: UUID, company_pk: UUID, user_pk: UUID, accessLevel: CompanyPermissionLevel.Value )

// associating data in an ad-hoc, not hard-coded way
for( ucp <- Query(UserCompanyPermissions).filter(_.accessLevel === LevelOne);
     c <- ucp.company;
     u <- ucp.user
) yield (u,c)

这里我们加载 u 和 c 因为我们是这么说的。我们可以只加载 u 或 c 或 c 和 ucp 或其他任何东西。它没有硬编码在我们的行类中。

在架构方面,您可以在我们的 Scala Days 2013 演讲和 Scala Exchange 2013 演讲中找到帮助。 http://slick.typesafe.com/docs/

作为一个侧节点,我会推荐一个sealed trait,带有case object children 而不是Enumeration for CompanyPermissionLevel .

关于database - Scala-Slick 中外键的类型投影,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20503847/

相关文章:

scala - 在 Play 中使用 Scala 2.9.2?

performance - 斯卡拉 : Writing String Iterator to file in Efficient way

scala - 避免创建几乎相同的案例类

scala - 保持数据库 session 打开

database - 每个页面 View 的成本更高 - 数据库写入还是文件写入?

sql - JdbcTemplate动态表名和SQL注入(inject)

swift - 在 Swift Core Data 中保存没有关系的实体

以部分函数为值的 Scala 映射

Slick 的 Mysql 版本

sql - 子表条件返回null