I've got a ManyToMany Relationship with composite key between a User and a Group in JPA EclipseLink. My Implementation looks like that:
User Class:
@Entity
@Table(name="mbm_user")
public class User extends CanAccessBook{
@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(nullable = false)
private Long id;
@OneToMany(mappedBy="user",cascade=CascadeType.PERSIST)
private List<GroupMembership> groups = new ArrayList<GroupMembership>();
/**
GETTER & SETTER
**/
}
Group Class:
@Entity
@Table(name="mbm_group")
public class Group extends CanAccessBook{
@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(nullable = false)
private Long id;
@OneToMany(mappedBy="group", cascade=CascadeType.PERSIST)
private List<GroupMembership> users = new ArrayList<GroupMembership>();
/**
GETTER & SETTER
**/
}
GroupMembership Class:
@Entity
@Table(name = "group_user")
@IdClass(UserGroupPK.class)
public class GroupMembership {
@Id
@ManyToOne
@PrimaryKeyJoinColumn(name="USERID")
private User user;
@Id
@ManyToOne
@PrimaryKeyJoinColumn(name="GROUPID")
private Group group;
@Temporal(TemporalType.DATE)
private Date joinedAt = new Date();
@Temporal(TemporalType.DATE)
private Date validUntil;
/**
GETTER & SETTER
**/
}
UserBookPK Class:
public class UserBookPK{
@Id
@Column(name="BOOKID")
private Long book;
@Id
@Column(name="USERID")
private Long user;
public Long getBook() {
return book;
}
public void setBook(Long book) {
this.book = book;
}
public Long getUser() {
return user;
}
public void setUser(Long user) {
this.user = user;
}
}
My JUnit Tests are report no errors, but if I test it on my Tomcat, I'm getting the following errors
Exception [EclipseLink-59] (Eclipse Persistence Services - 2.1.1.v20100817-r8050): org.eclipse.persistence.exceptions.DescriptorException Exception Description: The instance variable [groupId] is not defined in the domain class [de.kapieren.mbm.server.model.GroupMembership], or it is not accessible. Internal Exception: java.lang.NoSuchFieldException: groupId Mapping: org.eclipse.persistence.mappings.DirectToFieldMapping[groupId-->group_user.GROUPID] Descriptor: RelationalDescriptor(de.kapieren.mbm.server.model.GroupMembership --> [DatabaseTable(group_user)])
Exception [EclipseLink-59] (Eclipse Persistence Services - 2.1.1.v2开发者_运维问答0100817-r8050): org.eclipse.persistence.exceptions.DescriptorException Exception Description: The instance variable [userId] is not defined in the domain class [de.kapieren.mbm.server.model.GroupMembership], or it is not accessible. Internal Exception: java.lang.NoSuchFieldException: userId Mapping: org.eclipse.persistence.mappings.DirectToFieldMapping[userId-->group_user.USERID] Descriptor: RelationalDescriptor(de.kapieren.mbm.server.model.GroupMembership --> [DatabaseTable(group_user)])
Exception [EclipseLink-0] (Eclipse Persistence Services - 2.1.1.v20100817-r8050): org.eclipse.persistence.exceptions.DescriptorException Exception Description: An internal error occurred accessing the primary key object [202]. Internal Exception: java.lang.NoSuchFieldException: groupId Descriptor: RelationalDescriptor(de.kapieren.mbm.server.model.GroupMembership --> [DatabaseTable(group_user)])
Whats going wrong here?
You should be using @JoinColumn instead of @PrimaryKeyJoinColumn for the @ManyToOnes.
I tried the exactly same code with a windows machine and it works without problems. I think the problem is the JVM of MAC OS (I'm working with Mac OS). So I have to continue my work on a windows VM. this issue seems to be documented by EclipseLink (Exception 59). This is very bad for me and I think this will be my Last time I gave Java a try....
You have a UserBookPK
class, but it's not referenced anywhere else. I assume this is supposed to be UserGroupPK
? In which case it is wrong. The fields should be instances of User
and Group
, for one. It should be Serializable (but not include a version id, for some reason).
Better yet, don't use @IdClass
at all. It's only there for backwards compatibility. Put a surrogate key on GroupMemberShip
and use that to link everything together. Or if you really want the composite primary key, go for an @EmbeddedId
. Since this is just the relationship modelled as object, that does make some sense.
You don't necessarily need to map the intermediate class either, there is an @ManyToMany
that sometimes works.
精彩评论