使用Scala + Slick解决阻抗不匹配问题

时间:2014-10-20 11:21:26

标签: hibernate scala orm slick slick-2.0

假设我的数据库中有以下表格:

CREATE TABLE dealers(
 id INT PRIMARY KEY, 
 name VARCHAR(255)
);    

CREATE TABLE makers(
 id INT PRIMARY KEY, 
 name VARCHAR(255)
);

CREATE TABLE cars(
 id INT PRIMARY KEY, 
 make INT FOREIGN KEY makers(id), 
 model VARCHAR(255), 
 year INT
);

CREATE TABLE cars_in_dealers(
 car_id INT FOREIGN KEY cars(id), 
 dealer_id INT FOREIGN KEY dealers(id), 
 UNIQUE KEY (car_id, dealer_id)
);

鉴于这样的架构,我想使用Slick在Scala中加载经销商:

case class Dealer(id: Int, name: String, models: Set[Car])
case class Car(id: Int, make: Maker, model: String, year: Int)
case class Maker(id: Int, name: String)

有点复杂的事情:

如果我想跟踪每个经销商的模型数量,该怎么办:

case class Dealer(id: Int, name: String, models: Map[Car, Int])

这是我的映射表:

CREATE TABLE cars_in_dealers(
 car_id INT FOREIGN KEY cars(id), 
 dealer_id INT FOREIGN KEY dealers(id), 
 count INT,
 UNIQUE KEY (car_id, dealer_id)
);

我熟悉Ruby的ActiveRecord和Java的Hibernate框架,这些东西很容易做,但是我很难在Slick中完成它,因为Slick没有将嵌套模型映射到外键控表。我正在使用Slick的codegen,它只生成以下类:

case class DealersRow(id: Int, name: String)
case class MakersRow(id: Int, name: String
case class CarsRow(id: Int, make: Int, model: String, year: Int)
case class CarsInDealersRow(carId: Int, dealerId: Int)

1 个答案:

答案 0 :(得分:3)

使用查询做!来自the documentation

光滑的新来者经常会问他们如何在Slick中做这样的事情:

case class Address( … )
case class Person( …, address: Address )

问题在于,存在Person的硬编码需要一个地址。没有它就无法加载。这不适合Slick的理念,即让您对完全加载的内容进行细粒度控制。使用Slick时,建议将一个表映射到元组或案例类,而不使用对象引用相关对象。相反,您可以编写一个连接两个表并将它们作为元组或关联案例类实例返回的函数,在外部提供关联,而不是强烈绑定其中一个类。

val tupledJoin: Query[(People,Addresses),(Person,Address), Seq]
      = people join addresses on (_.addressId === _.id)

case class PersonWithAddress(person: Person, address: Address)
val caseClassJoinResults = tupledJoin.run map PersonWithAddress.tupled