无法使用 SkinnyORM 在模型的嵌套对象中检索嵌套对象列表
Cannot retrieve nested object list within nested object in model with SkinnyORM
我有一个模型 Contact 与模型 Role 有 hasMany 关系。
Model Role 与 Phone 具有 hasManyThrough 关系,中间 table RolePhone。
所有检索操作都设置为急切。
当我检索联系人时,我看到了它的角色列表,但每个角色都有一个空的 Phone 列表。但是当我检索所有角色时,他们的 Phone 列表包含正确的 Phones.
联系人和角色中的关系都被标记为默认值,我尝试手动设置角色的 joinDefinitions enabledEvenIfAssociated = true
但这些都不起作用
这些是我的模型,仅显示结构和关系
case class Contact(id: Long, name: String, roles: Seq[Role] = Nil)
object Contact extends SkinnyCRUDMapper[Contact] {
hasMany[Role](
Role -> Role.defaultAlias,
(contact, role) => sqls.eq(contact.id, role.contactId),
(contact, roles) => contact.copy(roles = roles),
).byDefault
}
case class RoleCommand(name: String, phoneNumbers: Seq[Int])
case class Role(id: Long, name: String, contactId: Long, phones: Seq[Phone] = Nil)
object Role extends SkinnyCRUDMapper[Role] {
hasManyThrough[RolePhone, Phone](
through = RolePhone -> RolePhone.defaultAlias,
throughOn = (r, rp) => sqls.eq(r.id, rp.roleId),
many = Phone -> Phone.defaultAlias,
on = (rp, p) => sqls.eq(rp.phoneId, p.id),
merge = (role, phones) => role.copy(phones = phones)
).byDefault
}
case class RolePhone(roleId: Long, phoneId: Long)
case class Phone(id: Long, number: Int)
这是我的数据库结构
create table contact (
id bigint(20) not null auto_increment primary key,
name varchar(50) not null unique
) engine=innoDB;
create table role (
id bigint(20) not null auto_increment primary key,
name varchar(50) not null unique,
contact_id bigint(20) not null
) engine=innoDB;
create table phone (
id bigint(20) not null auto_increment primary key,
number int(20) not null
) engine=innoDB;
create table role_phone (
role_id bigint(20) not null,
phone_id bigint(20) not null
) engine=innoDB;
这是一个 Main class 添加以暴露问题
object Main extends App with Connection with DatasourceConfig {
val contact1 = Contact.save("contact1",
Seq(
RoleCommand("role1", Seq(12345, 12321)),
RoleCommand("role2", Seq(54321, 12321)),
RoleCommand("role3", Seq(12345, 54321)),
)
)
// retrieving a contact won't fill the phones number inside each role
println(s"My Contact: ${Contact.findById(contact1)}")
// retrieving a role will fill the phones list
println(s"All Roles: ${Role.findAll()}")
}
完整代码位于 https://github.com/airabinovich/testing_skinny
我预计检索联系人会得到每个角色中的电话列表
按照上面的例子,应该是这样的
Contact(
1,
contact1,
Vector(
Role(1,role1,1,Vector(Phone(1,12345), Phone(2,12321))),
Role(2,role2,1,Vector(Phone(3,54321), Phone(2,12321))),
Role(3,role3,1,Vector(Phone(1,12345), Phone(3,54321)))
)
)
但我明白了
Contact(
1,
contact1,
Vector(
Role(1,role1,1,List()),
Role(1,role1,1,List()),
Role(2,role2,1,List()),
Role(2,role2,1,List()),
Role(3,role3,1,List()),
Role(3,role3,1,List())
)
)
与Kazuhiro Sera answered in his pull request一样,可以通过稍微改变一下关系来完成预先加载
object Contact extends SkinnyCRUDMapper[Contact] {
val rolesRef = hasMany[Role](
Role -> Role.defaultAlias,
(contact, role) => sqls.eq(contact.id, role.contactId),
(contact, roles) => contact.copy(roles = roles),
).includes[Role](
merge = (contacts, roles) => contacts.map(c => c.copy(roles = roles.filter(_.contactId == c.id)))
).byDefault
}
并且在从数据库中检索时包括关系
println(s"My Contact: ${Contact.includes(Contact.rolesRef).findById(contact1)}")
我有一个模型 Contact 与模型 Role 有 hasMany 关系。 Model Role 与 Phone 具有 hasManyThrough 关系,中间 table RolePhone。 所有检索操作都设置为急切。
当我检索联系人时,我看到了它的角色列表,但每个角色都有一个空的 Phone 列表。但是当我检索所有角色时,他们的 Phone 列表包含正确的 Phones.
联系人和角色中的关系都被标记为默认值,我尝试手动设置角色的 joinDefinitions enabledEvenIfAssociated = true
但这些都不起作用
这些是我的模型,仅显示结构和关系
case class Contact(id: Long, name: String, roles: Seq[Role] = Nil)
object Contact extends SkinnyCRUDMapper[Contact] {
hasMany[Role](
Role -> Role.defaultAlias,
(contact, role) => sqls.eq(contact.id, role.contactId),
(contact, roles) => contact.copy(roles = roles),
).byDefault
}
case class RoleCommand(name: String, phoneNumbers: Seq[Int])
case class Role(id: Long, name: String, contactId: Long, phones: Seq[Phone] = Nil)
object Role extends SkinnyCRUDMapper[Role] {
hasManyThrough[RolePhone, Phone](
through = RolePhone -> RolePhone.defaultAlias,
throughOn = (r, rp) => sqls.eq(r.id, rp.roleId),
many = Phone -> Phone.defaultAlias,
on = (rp, p) => sqls.eq(rp.phoneId, p.id),
merge = (role, phones) => role.copy(phones = phones)
).byDefault
}
case class RolePhone(roleId: Long, phoneId: Long)
case class Phone(id: Long, number: Int)
这是我的数据库结构
create table contact (
id bigint(20) not null auto_increment primary key,
name varchar(50) not null unique
) engine=innoDB;
create table role (
id bigint(20) not null auto_increment primary key,
name varchar(50) not null unique,
contact_id bigint(20) not null
) engine=innoDB;
create table phone (
id bigint(20) not null auto_increment primary key,
number int(20) not null
) engine=innoDB;
create table role_phone (
role_id bigint(20) not null,
phone_id bigint(20) not null
) engine=innoDB;
这是一个 Main class 添加以暴露问题
object Main extends App with Connection with DatasourceConfig {
val contact1 = Contact.save("contact1",
Seq(
RoleCommand("role1", Seq(12345, 12321)),
RoleCommand("role2", Seq(54321, 12321)),
RoleCommand("role3", Seq(12345, 54321)),
)
)
// retrieving a contact won't fill the phones number inside each role
println(s"My Contact: ${Contact.findById(contact1)}")
// retrieving a role will fill the phones list
println(s"All Roles: ${Role.findAll()}")
}
完整代码位于 https://github.com/airabinovich/testing_skinny
我预计检索联系人会得到每个角色中的电话列表 按照上面的例子,应该是这样的
Contact(
1,
contact1,
Vector(
Role(1,role1,1,Vector(Phone(1,12345), Phone(2,12321))),
Role(2,role2,1,Vector(Phone(3,54321), Phone(2,12321))),
Role(3,role3,1,Vector(Phone(1,12345), Phone(3,54321)))
)
)
但我明白了
Contact(
1,
contact1,
Vector(
Role(1,role1,1,List()),
Role(1,role1,1,List()),
Role(2,role2,1,List()),
Role(2,role2,1,List()),
Role(3,role3,1,List()),
Role(3,role3,1,List())
)
)
与Kazuhiro Sera answered in his pull request一样,可以通过稍微改变一下关系来完成预先加载
object Contact extends SkinnyCRUDMapper[Contact] {
val rolesRef = hasMany[Role](
Role -> Role.defaultAlias,
(contact, role) => sqls.eq(contact.id, role.contactId),
(contact, roles) => contact.copy(roles = roles),
).includes[Role](
merge = (contacts, roles) => contacts.map(c => c.copy(roles = roles.filter(_.contactId == c.id)))
).byDefault
}
并且在从数据库中检索时包括关系
println(s"My Contact: ${Contact.includes(Contact.rolesRef).findById(contact1)}")