Como você configurar uma relação muitos-para-muitos com a junção da tabela usando JPA / EclipseLink

StackOverflow https://stackoverflow.com/questions/878374

  •  22-08-2019
  •  | 
  •  

Pergunta

Eu tenho 2 tabelas:

Filmes: FilmeID

Usuários: userID

Estas tabelas têm um relacionamento muitos para muitos através da tabela de fila, com um atributo adicional, listOrder:

Fila: FilmeID, ID do usuário, listOrder

Eu estou tentando modelar isso usando EclipseLink, mas estou recebendo um erro "mapeamento incompattible". Aqui está uma amostra do meu código:


@Entity
@Table(name="movieinventory")
public class Movie implements Serializable
{
       private static final long serialVersionUID = 1L;

       @Id
       @GeneratedValue
       private Integer movieID;

       @OneToMany(mappedBy="movie")
       private Set moviesInQueue;

       ...Getters/Setters...
}

@Entity
@Table(name="Users")
public class User implements Serializable
{
       private static final long serialVersionUID = 1L;

       @Id
       @GeneratedValue
       private Integer userID;

       @OneToMany(mappedBy="user")
       private Set moviesInQueue;

      ...Getters/Setters...
}

@IdClass(QueueItemPK.class)
@Entity
@Table(name="queue")
public class QueueItem
{
       @Id
       @ManyToOne
       @JoinColumn(name="movieID")
       private Movie movie;

       @Id
       @ManyToOne
       @JoinColumn(name="userID")
       private User user;

       @Basic
       private String listOrder;

       ...Getters/Setters...
}

public class QueueItemPK implements Serializable
{
       private static final long serialVersionUID = 1L;

       private Movie movie;
       private User user;

       ...Getters/Setter...

       public int hashCode()
       {
           return (movie.getMovieID() + "|" + user.getUserID()).hashCode();
       }

       public boolean equals(Object obj)
       {
           if (obj == this) return true;
           if (obj == null) return false;
           if (!(obj instanceof QueueItemPK)) return false;
           QueueItemPK pk = (QueueItemPK) obj;
           return pk.movie.getMovieID() == movie.getMovieID() 
               && pk.user.getUserID() == user.getUserID();
       }
}

O objetivo da QueueItemPK é para que eu possa ter a primária composta chave de FilmeID e userID. Eu não estou absolutamente certo de que este é o caminho correto para fazê-lo.

Este é o erro: Exceção Descrição: Um mapeamento incompatível foi encontrado entre [Classe de filme] e [QueueItem classe]. Isso geralmente ocorre quando o cardinalidade de um mapeamento não corresponde com a cardinalidade do seu backpointer. Eu tenho o mesmo erro com a classe do usuário (os erros alternativo).

Quando eu tomar as anotações @ id fora das variáveis ??de cinema e de usuário em QueueItem e fazer alguma outra chave a chave primária, no entanto, ele compila com sem erros.

Todas as sugestões serão apreciadas.

Obrigado, B.J.

Foi útil?

Solução

Em primeiro lugar, como sugerido por Mike Cornell, o EmbeddedId / Class é provavelmente a escolha mais fácil de usar. No entanto, para responder à sua pergunta e código corrigido:

@IdClass(QueueItemPK.class)
@Entity
@Table(name="queue")
public class QueueItem
{
       @Id
       @ManyToOne(optional=false)
       @PrimaryKeyJoinColumn(name="movieID")
       private Movie movie;

       @Id
       @ManyToOne(optional=false)
       @PrimaryKeyJoinColumn(name="userID")
       private User user;

       @Basic
       private String listOrder;

       ...Getters/Setters...
}

public class QueueItemPK implements Serializable
{
       private static final long serialVersionUID = 1L;

       @Id
       @Column(name="movieID")
       private Integer movie;
       @Id
       @Column(name="userID")
       private Integer user;

       ...Getters/Setter...

       public int hashCode()
       {
           return (movie.getMovieID() + "|" + user.getUserID()).hashCode();
       }

       public boolean equals(Object obj)
       {
           if (obj == this) return true;
           if (obj == null) return false;
           if (!(obj instanceof QueueItemPK)) return false;
           QueueItemPK pk = (QueueItemPK) obj;
           return pk.movie == movie 
               && pk.user == user;
       }
}

Como você pode ver que é neccessary que eles têm o tipo de ID é que eles têm para corresponder. não muito bonito, mas de trabalho. E eu sugiro usar os genéricos para seus conjuntos; marcas ist mais fácil de ler e mais seguro para o código.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top