[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[
List Home]
[eclipselink-users] Removing from @ManyToMany collection doesn't work when JoinTable is joined by natural-keys (not PK)
|
Hi all, I have the following ManyToMany which fails to remove an entry in the join-table when an element in the list is removed:
I have a user, with natural key userName (unique) and each user can be member of several groups. Group has the natural-key groupName, and the join-table joins on their natural-keys.
The join-table is like this:
groupname | character varying | not null
username | character varying | not null
Indexes:
"onp_user_group_pkey" PRIMARY KEY, btree (groupname, username)
"onp_user_group_gropuname_idx" btree (groupname)
"onp_user_group_username_idx" btree (username)
Foreign-key constraints:
"$1" FOREIGN KEY (groupname) REFERENCES onp_group(groupname) ON UPDATE CASCADE ON DELETE CASCADE
"$2" FOREIGN KEY (username) REFERENCES onp_user(username) ON UPDATE CASCADE ON DELETE CASCADE
The entities, User and Group, are defined as:
@Entity
@Table(name = "onp_user")
@PrimaryKeyJoinColumn(name = "id")
@DiscriminatorValue("USER")
class User
@Id
@Column(name = "id", nullable = false)
Long id;
@Column(name = "username", unique = true, nullable = false)
String userName
...
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "onp_user_group",
joinColumns = {@JoinColumn(name = "username", referencedColumnName = "username")},
inverseJoinColumns = {@JoinColumn(name = "groupname", referencedColumnName = "groupname")}
)
List<Group> groups;
@Entity
@Table(name = "onp_group")
@PrimaryKeyJoinColumn(name = "id")
@DiscriminatorValue("GROUP")
class Group
@Id
@Column(name = "id", nullable = false)
Long id;
@Column(name = "groupname", unique = true, nullable = false)
String name;
The problem is that when removing an entry in user.groups, then the entry is not removed from the join-table "onp_user_group", because the query EL ends up executing is:
LOG: execute cached-531203064: DELETE FROM onp_user_group WHERE ((groupname = $1) AND (username = $2))
DETAIL: parameters: $1 = 'Somegroup', $2 = NULL
So NULL is passed as the value for "userName".
I see in the method (EL-source) CollectionMapping.writeChanges that the WriteObjectQuery passed as an argument (with argument-name "query") has a property "translationRow" which is used to map keys, and this Map contains the following when trying to persist changes:
onp_user.id=134
But RelationTableMechanism.addRelationTableSourceRow has the value "onp_user.username" in its sourceKeyFields, which doesn't map to an entry in the passed sourceRow. This results in the addRelationTableSourceRow method adding NULL as a value to key="onp_user.username", because sourceValue is assigned the value NULL:
public AbstractRecord addRelationTableSourceRow(AbstractRecord sourceRow, AbstractRecord databaseRow) {
int size = sourceKeyFields.size();
for(int i=0; i < size; i++) {
Object sourceValue = sourceRow.get(sourceKeyFields.get(i));
databaseRow.put(sourceRelationKeyFields.get(i), sourceValue);
}
return databaseRow;
}
So, is there a way to make this work, or do I have to use primary keys in the join-table? Everything else works nicely, just not removing.
Thanks.
--
Andreas Joseph Krogh
CTO / Partner - Visena AS
Mobile: +47 909 56 963