【问题标题】:How to organise the entity model for play framework 2 when working with anorm使用 anorm 时如何为 play framework 2 组织实体模型
【发布时间】:2014-04-21 11:44:14
【问题描述】:

我有一个包含一组字段和外键的表。

使用 Ebean 时,我可以指定要填写请求的字段,仅从以外部关系结尾的 id 开始(并不总是需要将数据库中的所有字段都包含在类中)。它只使用一个绑定到表的类。

@Entity
public class Product extends Model{   

@Id
public Long id;

@Constraints.Required
public String name;

@Lob
public String description;

@ManyToOne
public Trademark trademark;

...

}

第一季度。使用 Anorm 时鼓励使用 case class,但我需要指定 case class 的所有可能字段并填写它们。如果我只需要带有字段IdName 的对象,或者只需要带有Id 的引用对象?我必须描述另一个类?

case class ProductRef (id: Pk[Long] = NotAssigned)
case class Product (id: Pk[Long] = NotAssigned, name: String)
case class ProductWithTrademark (id: Pk[Long] = NotAssigned, name: String, trademark: Trademark)
...
case class Trademark (id: Pk[Long] = NotAssigned, name: String ="")

第二季度。如果可以将此表用作另一个表中的外键怎么办?使用哪个case class

case class Size(id: Pk[Long] = NotAssigned, name: String)
case class ProductSize(id: Pk[Long] = NotAssigned, product: ??? , size: Size)

第三季度。或者最好总是用默认值填充所有字段并只使用一个case class

case class Product(id: Pk[Long] = NotAssigned, name: String="", trademark: Trademark = Trademark())
case class Trademark(id: Pk[Long] = NotAssigned, name: String="")
case class Size(id: Pk[Long] = NotAssigned, name: String = "")
case class ProductSize(id: Pk[Long] = NotAssigned, product: Product = Product(), size: Size = Size())

第四季度。还是有正确的决定我根本不知道

【问题讨论】:

    标签: scala playframework-2.0 anorm


    【解决方案1】:

    当您的表中有几个可以为空的字段时,通常的做法是在您的案例类中将它们设置为选项。例如,而不是:

    case class Product (id: Pk[Long] = NotAssigned, name: String)
    case class ProductWithTrademark (id: Pk[Long] = NotAssigned, name: String, trademark: Trademark)
    

    你会:

    case class Product (id: Pk[Long] = NotAssigned, name: String, trademark: Option[Trademark])
    

    然后设置你的产品解析器来检查Trademark是否存在。


    Play 附带的 computer-database 示例描述了完全相同的情况。在该示例中,他们使用以下案例类来描述他们的模型:

    case class Company(id: Pk[Long] = NotAssigned, name: String)
    case class Computer(id: Pk[Long] = NotAssigned, name: String, introduced: Option[Date], discontinued: Option[Date], companyId: Option[Long])
    

    您可以看到外键设置为Option,因为Computer 模型可以(没有)Company 链接到它。 Computer 解析器描述如下:

    val simple = {
        get[Pk[Long]]("computer.id") ~
        get[String]("computer.name") ~
        get[Option[Date]]("computer.introduced") ~
        get[Option[Date]]("computer.discontinued") ~
        get[Option[Long]]("computer.company_id") map {
          case id~name~introduced~discontinued~companyId => Computer(id, name, introduced, discontinued, companyId)
        }
    }
    

    注意在解析外键时如何使用get[Option[Long]]。 公司解析器的定义方式相同,当想要同时获取ComputerCompany时(如果设置了外键company_id),他们使用了以下返回元组(Computer,Option[Company])的解析器:

    val withCompany = Computer.simple ~ (Company.simple ?) map {
        case computer~company => (computer,company)
    }
    

    【讨论】:

    • 也许我无法描述我想要什么。当然nullable 数据库的字段在应用程序中必须是optional,但是我的问题是在仅从数据库中读取 id+name时使用case class 而不填写 all 字段>(例如,如果部分代码只需要它们)。
    • 啊我现在明白了,要么创建新的案例类,要么将所有字段作为选项,如上所述。
    • 使用两种解决方案怎么样?将option 与默认None 一起使用?
    • 实际上,如果该字段为空,上述解析器会自动返回 None。现在,没有什么能阻止您将它们默认设置为 null,因为有时您需要创建一个案例类并对其进行处理,或者只是在将相应信息插入数据库之前。所以,是的,你可以同时做这两件事。
    • 没错。 null in case class 为默认值,Option 为数据库可为空的值。如果在数据库中存储了null 解析器将None 放入case class 字段中
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-19
    • 2018-07-19
    • 2014-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多