0

我正在从事的项目遇到了一些不良的 Mapper 行为。除非对象已经保存在数据库中,否则您似乎无法将对象添加到多对多关联中(更具体地说,您无法从多对多关联中检索一些未保存的对象)。

例如,我们有 M:N 关系中的员工和部门。我们实例化 2 个部门:会计和安全。会计在员工获救之前获得员工,安全部门在员工获救后获得员工。

object Employee extends Employee with LongKeyedMetaMapper[Employee]
class Employee extends LongKeyedMapper[Employee] with IdPK {
  def getSingleton = Employee
  object name extends MappedString(this, 20)
  override def toString = name.get
}

object Department extends Department with LongKeyedMetaMapper[Department]
class Department extends LongKeyedMapper[Department] with ManyToMany with IdPK {
  def getSingleton = Department
  object employees extends MappedManyToMany(
    EmployeeDepartment,
    EmployeeDepartment.department,
    EmployeeDepartment.employee,
    Employee)
}

/* Many-to-Many association record */
object EmployeeDepartment extends EmployeeDepartment with LongKeyedMetaMapper[EmployeeDepartment]
class EmployeeDepartment extends LongKeyedMapper[EmployeeDepartment] with IdPK {
  def getSingleton = EmployeeDepartment

  object employee extends MappedLongForeignKey(this, Employee)
  object department extends MappedLongForeignKey(this, Department)
}

object Company extends App {
  DB.defineConnectionManager(DefaultConnectionIdentifier, myDBVendor)

  val accounting = Department.create
  val security = Department.create

  accounting.employees ++= Seq(
    Employee.create.name("Fred"),
    Employee.create.name("Steve"))

  security.employees ++= Seq(
    Employee.create.name("Dave"),
    Employee.create.name("Sonia")) map
    {_.saveMe()}

  accounting.employees.toList map println; println
  security.employees.toList map println
}

输出

弗雷德
弗雷德

戴夫
索尼娅

!!!

会计的员工都变成了弗雷德!问题的规模相似:添加 10 个尚未保存的实体以accounting.employees在访问时产生 10 个对 Fred 的引用。

这似乎是一个错误,或者是对 Mapper 有用性的严重限制。是否有不涉及任何一种行为的解决方法:

  • 使用模型外部的一些数据结构来跟踪实体和关联,直到您准备好保存,或者
  • 在创建时保存实体,如果用户“改变主意”关于保存,则发出删除
4

1 回答 1

0

找出造成这种明显不当行为的具体原因。将元素添加到多对多关联会调用以下算法:

在“this”连接列表中查找“other”元素。
如果没有找到
  创建加入并添加到加入列表
别的
  添加到加入列表

问题在于查找标准。在 ManyToMany.scala (Lift 2.4) 中指定,方法isJoinForChildis关联外键(构造函数参数 3)与“其他”元素 MappedManyToMany的主键(也是)进行比较。is

由于每个未保存实体with IdPK的 id=-1,“this”连接列表中的第一个元素满足查找条件,然后重复添加。

这回答了我最初的问题:可以通过修改isJoinForChild. 该方法不是简单地比较键,而是执行类似于:

如果 other.is > -1
  定期比较
别的
  实例比较

......或类似的东西。因为isJoinForChild这可以通过使用特征protected覆盖来非侵入性地完成。isJoinForChild

于 2012-11-02T14:22:51.173 回答