我正在使用Scala,而且是Play和Slick的新手.我开始阻止一个简单的数据库结构,我不确定处理外键和投影的正确方法.在页面底部的示例中,它目前无法编译,因为无法直接提取ForeignKey,因此将查询结果提升到我的类型(这基本上是sans方法和其他构造函数)的正确方法是什么:
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) } }
cvogt.. 7
使用Slick的推荐方法是永远不会嵌套包含行值的case类.它们应该只包含实际的列,而不是任何相关的对象,因为它会硬编码它们必须一起加载(除非你在引擎盖下做一些神奇的延迟加载,这使得使用和实现复杂).相反,您编写查询,使用元组将您现在需要的特定数据的值关联起来.
// 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
孩子而Enumeration
为CompanyPermissionLevel
.