【发布时间】:2014-07-07 15:18:03
【问题描述】:
我正在使用 play 2.3 和 slick 2.1
我有两个相关实体 - Message 和 User(一个简化的示例域)。消息由用户编写。
表达这种关系的A recommended way (the only way?)是在Message中使用显式userId
我的类和表映射如下所示:
case class Message (
text: String,
userId: Int,
date: Timestamp = new Timestamp(new Date().getTime()),
id: Option[Int] = None) {}
case class User (
userName: String,
displayName: String,
passHash: String,
creationDate: Timestamp = new Timestamp(new Date().getTime()),
lastVisitDate: Option[Timestamp] = None,
// etc
id: Option[Int] = None){}
class MessageTable(tag: Tag) extends Table[Message](tag, "messages") {
def id = column[Int]("id", O.PrimaryKey, O.AutoInc)
def text = column[String]("text")
def userId = column[Int]("user_id")
def date = column[Timestamp]("creation_date")
def * = (title, text, userId, date, id.?) <> (Post.tupled, Post.unapply
def author = foreignKey("message_user_fk", userId, TableQuery[UserTable])(_.id)
}
class UserTable(tag: Tag) extends Table[User](tag, "USER") {
def id = column[Int]("id", O.PrimaryKey, O.AutoInc)
def username = column[String]("username")
def passHash = column[String]("password")
def displayname = column[String]("display_name")
def * = (username, passHash,created, lastvisit, ..., id.?) <> (User.tupled, User.unapply)
}
还有一个方便的辅助对象:
object db {
object users extends TableQuery(new UserTable(_)) {
// helper methods, compiled queries
}
object messages extends TableQuery(new MessageTable(_)) {
// helper methods, compiled queries
}
}
现在,这在内部已经很完美了,但是如果我想显示实际的消息,我希望消息类在模板中使用时能够返回它的作者姓名。
以下是我的考虑:
- 我不希望(而且我无论如何也不能)在不属于它的地方传递隐式光滑
Session- 例如模板引擎和模型类 - 在这种特殊情况下,我希望避免为消息逐一请求额外数据
我对 Hibernate 比对 Slick 更熟悉;在 Hibernate 中,我会使用 join-fetching。对于 Slick,我想出的最佳想法是使用另一个数据保持器类进行显示:
class LoadedMessage (user:User, message:Message) {
// getters
def text = message.text
def date = message.date
def author = user.displayName
}
object LoadedMessage {
def apply( u:User , m:Message ) = new LoadedMessage(u, m)
}
并用连接查询的结果填充它:
val messageList: List[LoadedMessage] = (
for (
u <- db.users;
m <- db.messages if u.id === m.userId
) yield (u, m))
.sortBy({ case (u, m) => m.date })
.drop(n)
.take(amount)
.list.map { case (u, m) => LoadedMessage(u, m) }
然后将它传递到任何地方。我关心的是这个额外的类 - 不是很干燥,所以不必要的转换(而且似乎我不能让它隐含),很多样板。
常用的方法是什么? 有没有办法减少额外的类并真正使模型能够返回它的关联?
【问题讨论】:
-
只是一个考虑因素,
Hibernate是一个 ORM,而Slick是一个允许您编写类型安全查询的层,您不能指望相同的功能,在这种情况下尤其是您可以除非您在使用连接的查询中指定,否则不要期望 Slick 为您获取对象。如果您更喜欢 ORM,请查看 SQueryl 例如。 -
我不喜欢编写查询或加入表格。我对如何以有效的方式表示结果感到更加困惑
-
感谢您的提示,我也会看看 Squeryl。我刚开始玩 Play,几乎整个堆栈都不熟悉。
标签: scala playframework-2.0 slick-2.0