【问题标题】:Solving O/R Impedence mismatch using Scala + Slick使用 Scala + Slick 解决阻抗不匹配问题
【发布时间】:2014-10-20 21:08:43
【问题描述】:

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

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 的代码生成器,它只生成以下类:

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)

【问题讨论】:

  • 你不应该(也可能不能),slick 为你的模式创建一个模型并且你的模式有外键,你可以在查询执行后将它映射到你想要的,这已经问了很多,hereherehere 仅举几例。
  • Slick 不是也不应该用作 ORM。不要尝试将外键映射到除了聚合根之外的序列(在这种情况下,不要尝试懒惰地加载它们)。它只是行不通。太复杂了。
  • 你在 Scala 中推荐什么是 ORM 的好库?我在 Slick 中大约 50% 的代码将所有这些连接和元组转换写入嵌套模型。我想要一些开箱即用的东西,我的面向对象模型巧妙地映射到开箱即用的关系数据库..

标签: hibernate scala orm slick slick-2.0


【解决方案1】:

使用查询来实现!来自the documentation

Slick 新人经常问他们如何在 Slick 中做这样的事情:

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

问题在于这种硬编码要存在一个人需要一个地址。没有它就无法加载。这不符合 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-05
    • 1970-01-01
    • 2018-01-30
    • 2019-01-27
    • 1970-01-01
    • 2021-03-20
    相关资源
    最近更新 更多