2012-07-16 41 views
2

我需要在Scala中完成許多對象的多對多映射,並將其保存到關係數據庫中。如何用Scala建模關係數據庫鏈接表?

這是一個假的例子,以簡化問題:

比方說,我們希望教室和學生進行建模。演講室可能有許多學生,但這些學生也可以去不同的房間。從關係數據庫模型的角度來看,您將創建3個表格,一個用於ROOM,一個用於STUDENT,另一個用於鏈接學生和房間ROOM_STUDENT。

比方說,表是這樣的:

ROOM 
----- 
id 
subject 

STUDENT 
------- 
id 
name 

ROOM_STUDENT 
------------- 
room_id 
student_id 

如果我想使用Scala的訪問(也許創建)這樣的數據庫,怎麼會用,比如,ScalaQuery或SLICK,或做有更好的Scala解決方案嗎?我是否應該以某種方式使用case類,或者以某種方式使用舊的SQL?

我基本上希望在這裏有兩個提示,1.一個很好的方式來介紹Scala中的STUDENT和ROOM,2.一些關於這個問題的關係數據庫持久性的想法。

回答

3

我個人比較喜歡Lift's Mapper library,偶爾會在Lift Web應用程序的上下文之外使用它。下面是一個完整的工作示例,您可以從sbt例如用作爲build.sbt下運行:

libraryDependencies ++= Seq(
    "net.liftweb" %% "lift-mapper" % "2.4" % "compile->default", 
    "com.h2database" % "h2" % "1.2.127" 
) 

首先爲模特:

import net.liftweb.common._, net.liftweb.mapper._ 

object Student extends Student with LongKeyedMetaMapper[Student] 
class Student extends LongKeyedMapper[Student] with IdPK with ManyToMany { 
    def getSingleton = Student 
    object name extends MappedString(this, 40) 
    object rooms extends MappedManyToMany(
    StudentRoom, StudentRoom.student, StudentRoom.room, Room 
) 
} 

object Room extends Room with LongKeyedMetaMapper[Room] 
class Room extends LongKeyedMapper[Room] with IdPK with ManyToMany { 
    def getSingleton = Room 
    object subject extends MappedString(this, 40) 
    object students extends MappedManyToMany(
    StudentRoom, StudentRoom.room, StudentRoom.student, Student 
) 
} 

object StudentRoom extends StudentRoom with LongKeyedMetaMapper[StudentRoom] { 
    override def dbIndexes = Index(student, room) :: super.dbIndexes 
} 

class StudentRoom extends LongKeyedMapper[StudentRoom] with IdPK { 
    def getSingleton = StudentRoom 
    object student extends MappedLongForeignKey(this, Student) 
    object room extends MappedLongForeignKey(this, Room) 
} 

和一些數據庫設置:

DB.defineConnectionManager(
    DefaultConnectionIdentifier, 
    new StandardDBVendor("org.h2.Driver", "jdbc:h2:mem:example", Empty, Empty) 
) 

Schemifier.schemify(true, Schemifier.infoF _, Student, Room, StudentRoom) 

還有一些數據:

val m = Student.create.name("Mary"); m.save 
val j = Student.create.name("John"); j.save 
val physics = Room.create.subject("Physics"); physics.save 
StudentRoom.create.student(m).room(physics).save 
StudentRoom.create.student(j).room(physics).save 

我們準備:

scala> Room.findAll(By(Room.subject, "Physics")).flatMap(_.students) 
res7: List[Student] = List(Student={name=Mary,id=2}, Student={name=John,id=3}) 
+0

非常感謝您特拉維斯。我之前沒有使用過Lift。你知道我可以添加到build.sbt只使用映射器的最小存儲庫是什麼?例如,如果我想用SBT運行你的例子?有趣的位接縫是:「net.liftweb」%%「lift-mapper」%liftVersion%「compile-> default」。我從http://www.assembla.com/wiki/show/liftweb/Using_SBT/得到了這個。 – Jack 2012-07-17 03:07:56

+0

@JacobusR:我在你的配置中添加了一行你需要的編輯。 – 2012-07-17 03:22:30

+0

特拉維斯,你是百萬分之一,謝謝。 – Jack 2012-07-17 03:45:52