The project I am working on has run into some undesirable Mapper behaviour. It seems you cannot add objects to many-to-many associations unless the objects are already saved in the database (more specifically, you cannot retrieve some not-saved objects from many-to-many associations).
As an example we have Employees and Departments in an M:N relationship. We instantiate 2 departments: Accounting and Security. Accounting gets employees before they are saved, Security gets employees after they are saved.
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
}
Output
Fred Fred Dave Sonia
!!!
The employees of accounting have all turned into Fred! The problem scales similarly: adding 10 not-yet-saved entities to accounting.employees
yields 10 references to Fred on access.
This appears to either be a bug, or a serious limitation to the usefulness of Mapper. Is there a workaround for this behaviour that does not involve either:
- using some data structure external to the model to keep track of entities and associations until you are ready to save, or
- saving entities on create, issuing deletes if the user "changes their mind" about saving