Проблема с ManyToMany и JPA EclipseLink - PullRequest
2 голосов
/ 11 ноября 2010

У меня есть отношения ManyToMany с составным ключом между пользователем и группой в JPA EclipseLink. Моя реализация выглядит так:

Класс пользователя:

@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
  **/
}

Групповой класс:

@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
  **/
}

Класс членства в группе:

@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 Класс:

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;
}
}

Мои тесты JUnit не сообщают об ошибках, но если я тестирую их на своем Tomcat, я получаю следующие ошибки

Исключение [EclipseLink-59] (Eclipse Persistence Services - 2.1.1.v20100817-r8050): org.eclipse.persistence.exceptions.DescriptorException Описание исключения: переменная экземпляра [groupId] не определена в классе домена [de.kapieren.mbm.server.model.GroupMembership] или недоступна. Внутреннее исключение: java.lang.NoSuchFieldException: groupId Отображение: org.eclipse.persistence.mappings.DirectToFieldMapping [groupId -> group_user.GROUPID] Дескриптор: RelationalDescriptor (de.kapieren.mbm.server.model.GroupMembership -> [DatabaseTable (group_user)]))

Исключение [EclipseLink-59] (Eclipse Persistence Services - 2.1.1.v20100817-r8050): org.eclipse.persistence.exceptions.DescriptorException Описание исключения: переменная экземпляра [userId] не определена в классе домена [de.kapieren.mbm.server.model.GroupMembership] или недоступна. Внутреннее исключение: java.lang.NoSuchFieldException: userId Отображение: org.eclipse.persistence.mappings.DirectToFieldMapping [userId -> group_user.USERID] Дескриптор: RelationalDescriptor (de.kapieren.mbm.server.model.GroupMembership -> [DatabaseTable (group_user)]))

Исключение [EclipseLink-0] (Eclipse Persistence Services - 2.1.1.v20100817-r8050): org.eclipse.persistence.exceptions.DescriptorException Описание исключения: произошла внутренняя ошибка при доступе к объекту первичного ключа [202]. Внутреннее исключение: java.lang.NoSuchFieldException: groupId Дескриптор: RelationalDescriptor (de.kapieren.mbm.server.model.GroupMembership -> [DatabaseTable (group_user)]))

Что здесь не так?

Ответы [ 3 ]

1 голос
/ 12 ноября 2010

Вы должны использовать @JoinColumn вместо @PrimaryKeyJoinColumn для @ ManyToOnes.

0 голосов
/ 12 ноября 2010

У вас есть класс UserBookPK, но на него больше нет ссылок. Я предполагаю, что это должно быть UserGroupPK? В этом случае это неправильно. Поля должны быть экземплярами User и Group для одного. Он должен быть Serializable (но по какой-то причине не включать идентификатор версии).

Еще лучше, не используйте @IdClass вообще. Это только для обратной совместимости. Поместите суррогатный ключ на GroupMemberShip и используйте его, чтобы связать все вместе. Или, если вы действительно хотите составной первичный ключ, выберите @EmbeddedId. Поскольку это просто отношения, смоделированные как объект, это имеет некоторый смысл.

Вам также не обязательно отображать промежуточный класс, есть @ManyToMany, который иногда работает.

0 голосов
/ 12 ноября 2010

Я попробовал точно такой же код на машине с Windows, и он работает без проблем.Я думаю, что проблема в JVM MAC OS (я работаю с Mac OS).Поэтому я должен продолжить свою работу на Windows VM.эта проблема, кажется, задокументирована EclipseLink (исключение 59).Это очень плохо для меня, и я думаю, что это будет мой последний раз, когда я попробовал Java ...

...