我正试图在现实生活中使用Slick的嵌入式嵌入方法(体育俱乐部成员的个人数据自我管理) . 我已经设法从数据库中检索信息并更新记录(实现Member作为案例类并使用案例类复制方法,如下所示)但我很难找到实现成员修改的最佳方法 . 自然的方式 .
我已经考虑了两种可能性:1)维护类实例的不变性并实现一般的setter(参见代码)2)使构造函数参数“var”(什么会抑制不变性,因此不理想)
坚持使用选项1,我想出了以下代码(摘录,而不是整个源代码):
case class Member(id: Int, name: String, firstname: Option[String] = None,
birthDate: Option[Date] = None, gender: Option[String] = None, country: Option[String] = None,
healthNotes: Option[String]) {
// Just a try so far
def set(n: String = name, fn: Option[String] = firstname, bd : Option[Date] = birthDate)
(implicit session: Session) = {
val m = this.copy(id,n,fn,bd)
Members.update(m)
m
}
}
object Members extends Table[Member]("clubmembers")
with CayenneAutoPKSupport {
def id = column[Int]("Member_ID", O.PrimaryKey) // This is the primary key column
def name = column[String]("Name")
def firstname = column[Option[String]]("Firstname")
def birthDate = column[Option[Date]]("BirthDate")
def gender = column[Option[String]]("Gender")
def country = column[Option[String]]("Country")
def healthNotes = column[Option[String]]("HealthNotes")
// Every table needs a * projection with the same type as the table's type parameter
def * = id ~ name ~ firstname ~ birthDate ~ gender ~ country ~ healthNotes <> (Member.apply _, Member.unapply _)
}
这按预期工作,但我希望set方法的命名参数具有相同的名称(什么会使调用更“自然”) . 我尝试了以下(无济于事)
def set( name: String = this.name, …
这不编译,我可以想象为什么编译器不满意(OTOH当前的实现似乎工作)但我也可以想象它可以工作 . 无论如何:有人看到了实现这一目标的方法吗?
或者,作为Slick持久化对象实现可修改类实例的最佳实践,会建议什么?
提前感谢任何提示 .
问候
2 回答
实际上,如果对参数和默认值使用相同的名称,原始代码将起作用 . 它只是Scala IDE中的语法高亮显示器似乎无法理解:如果名称不同,默认值(正确)突出显示为类成员,它们只是显示为名称相同的参数本身 .
这是当前版本(按预期工作但未正确语法突出显示):
注意:字符串参数最好也作为Option [String]传递 .
欢迎提出意见和建议 .
问候
如果这是你想要实现的目标,这将为我编译:
我不建议在你的case类中做数据库函数 . 我们通常使用案例类作为简单的数据存储对象,并且只定义有助于管理该数据的函数 .
成员的更新应该在您的成员DAO类中进行,可能最简单的解决方案是这样的:
处理可修改类的另一个解决方案是使用以下行的模式:
最后,如果你想要一个保存函数,你可以通过隐式语法注入一个流畅的样式语法,它总是返回一个定义了保存函数的新成员 .
希望您能找到一些有用的选项 . 如果我误解了你的要求,那么请评论!
更新
您不一定要为每个成员都有一个更新方法,但您可能会在那里执行其他逻辑 . 如果您想要一个简单的解决方案,那么就像使用Scala的内置复制功能一样 .
如果这对您不起作用,请解释原因 .
我在基本上存储数据的类中使用save方法的问题是它没有考虑Seperation of Concerns . 此外,您的设置功能也有副作用,这可能会使其他开发人员感到困惑(并且功能不太强) . 如果您只想设置名字然后将其传递到另一个类来设置生日,该怎么办?你想做两个数据库事务吗?我猜不会 .
这就是Data Access Object and its advantages发挥作用的地方 . 您可以将案例类的所有数据库操作放在一个类中,从而分离关注点:您的案例类包含数据并且具有仅对数据执行操作的函数,并且您的DAO具有查询/持久化/更新/删除您的案例类 . 这也使得测试应用程序变得更加容易,因为它保存了函数 .
很多人_1116209_,这些陈述只是我的意见 .
不使用DAO
我建议为可更新的案例类定义一个特征:
这些只是想法,我认为没有正确或错误的解决方案 . 选择一个对您有意义的,并为您提供必要的可用性/灵活性比率 .
最佳做法
您询问了Scala最佳实践 . 您的问题更多的是软件设计问题,因此阅读一般的OO软件设计可以帮助您 . Scala的案例类别非常多更简单的编写POJO的方法 . 因此,在将任何新函数添加到案例类之前,请问自己一个问题:“我会把它放在POJO中吗?” . 如果是的话,那就继续吧:)