2013-12-10 24 views
7

Scala'yı kullanıyorum ve Play and Slick'te yeni. Basit bir veritabanı yapısını engellemeye başladım ve yabancı anahtarların ve projeksiyonların üstesinden gelmenin doğru yolu hakkında emin değilim.Scala-Slick'te Yabancı Anahtarların Türlerini Gösterme

case class UserCompanyPermission(pk: UUID, company: Company, user: User, accessLevel: CompanyPermissionLevel) 
: ForeignKey doğrudan kaldırdı olamaz çünkü sayfa altındaki örnekte şu anda bu yüzden sorgu sonuçları (temelde sans yöntemleri ve ek kurucular bu olan) benim türü içine asansör olması doğru yolu nedir, derleme değil

İsterseniz, tür projeksiyonunun bir UserCompanyPermission döndürmesini isterim, aksi takdirde DAO yöntemlerine giren ve çıkan herşeyi sarmak için bir yolum var, bu yüzden Scala Tiplerimi geçiyorum. Temel olarak emin olmak istiyorum İş mantığım tamamen testten çıkarmayı kolaylaştırmak için tamamen devletten ayrıştırıldı, böylece tüm tablo özellikleri bu depolama paketiyle sınırlı tutulabildi. Paketleme yolu var mı, yoksa DAO nesnesine yazdığım her bir yöntemi, dönüştürmeyi kendi başına yapmam gerekecek mi?

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) 
    } 
} 
+0

Ayrıca, bu sorunun farkındayım, ancak doğru tasarım yaklaşımının ne olacağı konusunda hiçbir ayrıntıya girmiyor. http://stackoverflow.com/questions/17830492/how-to-use-slicks-mapped-tables-with-foreign-keys – MalucoMarinero

cevap

6

Slick ile çalışmanın önerilen yolu, satırlarınızın değerlerini tutan vaka sınıflarını hiçbir zaman yuvalamaktır. Sadece ilgili sütunları değil, gerçek nesneleri içermelidirler, çünkü bu onların bir araya getirilmeleri zor bir kod olurdu (kaputun altında sihirli bir tempolu yükleme yapmadıkça, kullanım ve uygulama için işleri karmaşık hale getirir). Bunun yerine, şu anda ihtiyaç duyduğunuz belirli verilerin değerlerini tuples kullanarak ilişkilendiren sorguları yazarsınız.

// 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) 

Burada u ve c'yi yüklüyoruz, çünkü öyle diyoruz. Sadece c veya c veya c ve ucp veya neyse yükleyebilirdik. Sıra sınıflarımızda kodlanmış değil.

Mimarlık-bilge, Scala Days 2013 konuşmamızda ve Scala Exchange 2013 konuşmasında yardım bulabilirsiniz. http://slick.typesafe.com/docs/

bir yan düğümü olarak ben bir sealed traitcase object çocuklara yerine CompanyPermissionLevel için Enumeration öneriyoruz.

+0

Evet, bu çok mantıklı. Sanırım birincil Python/Django arka planından gelen beklenmedik bir sınırlama gibi görünüyordu, ama elbette veritabanını kullanımınızı kelepçelenmeyen, güvenli bir şekilde işleri yapmanın tek yolu bu. Numaralandırma ile ilgili ipucu için de alkış. – MalucoMarinero

+0

Daha fazla geçerli bir ORM -> ilişkisel/işlevsel karışıklık olduğunu düşünüyorum. ORM'ler, manşetleri serbest bırakmak için tembel yükleme sihrini kullanırlar. Slick, ilişki söz konusu olduğunda açıklığın örtük olduğundan daha iyi olduğuna inanıyor. Scala toprağına hoşgeldiniz :). – cvogt

İlgili konular