JPA - Dúvida sobre mapeamento de um relacionamento composto [RESOLVIDO]

2 respostas
ricardospinoza

Pessoal,

no banco de dados:

G_PERFIL
 ID_PERFIL (PK)
 DESCRICAO
 SITUACAO
 DATA_CRIACAO
 ID_USUARIO (FK)

G_PERFIL_ACAO
 ID_PERFIL (PK)
 ID_ACAO   (PK)
 CODIGO
 DESCRICAO

G_ACAO
 ID_ACAO (PK)
 DESCRICAO
 COD_ACAO

A tabela G_PERFIL_ACAO é de muitos pra muitos entre G_PERFIL e G_ACAO

No java tenho as seguintes classes para representar este caso:

Classe: Perfil

@Entity
@Table(name = "g_perfil")
public class Perfil implements Serializable {

    private static final long serialVersionUID = 1L;
    @SequenceGenerator(sequenceName = "perfil_seq", name = "perfil_seq", allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "perfil_seq")
    @Id
    @Basic(optional = false)
    @Column(name = "id_perfil", nullable = false)
    private Integer id;
    @Column(name = "descricao", length = 20)
    private String descricao;
    @Column(name = "situacao")
    private Integer situacao;
    @Column(name = "data_criacao")
    @Temporal(TemporalType.TIMESTAMP)
    private Date dataCriacao;
    @JoinColumn(name = "id_usuario", referencedColumnName = "id_usuario")
    @ManyToOne(fetch = FetchType.EAGER)
    private Usuario usuario;

    @JoinColumn(name = "id_perfil", referencedColumnName = "id_perfil")
    @ManyToOne(fetch = FetchType.LAZY)
    private PerfilAcao perfilAcao;
   //omiti getters e setters ...
}

Classe: PerfilAcao

@Entity
@Table(name = "g_perfil_acao")
public class PerfilAcao implements Serializable {
    private static final long serialVersionUID = 1L;
    @EmbeddedId
    protected PerfilAcaoPK perfilAcaoPK;
    @Column(name = "descricao_modulo", length = 20)
    private String descricaoModulo;
    @Column(name = "cod_modulo")
    private Integer codModulo;
    @JoinColumn(name = "id_acao", referencedColumnName = "id_acao", nullable = false, insertable = false, updatable = false)
    @ManyToOne(optional = false, fetch = FetchType.EAGER)
    private Acao acao;
    @JoinColumn(name = "id_perfil", referencedColumnName = "id_perfil", nullable = false, insertable = false, updatable = false)
    @ManyToOne(optional = false, fetch = FetchType.EAGER)
    private Perfil perfil;

   //omiti getters e setters ...
}

Classe: PerfilAcaoPK

@Embeddable
public class PerfilAcaoPK implements Serializable {
    @Basic(optional = false)
    @Column(name = "id_perfil", nullable = false)
    private int idPerfil;
    @Basic(optional = false)
    @Column(name = "id_acao", nullable = false)
    private int idAcao;
   //omiti getters e setters ...
}

Classe: Acao

@Entity
@Table(name = "g_acao")
public class Acao implements Serializable {
    private static final long serialVersionUID = 1L;
    @SequenceGenerator(sequenceName="acao_seq", name = "acao_seq", allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "acao_seq")
    @Id
    @Basic(optional = false)
    @Column(name = "id_acao", nullable = false)
    private Integer id;
    @Column(name = "descricao", length = 20)
    private String descricao;
    @Column(name = "cod_acao", nullable = false)
    private Integer codigo;
    //omiti getters e setters ...
}

A exceção que dispara é a seguinte:

Root cause:

Exception [EclipseLink-7220] (Eclipse Persistence Services - 2.0.0.v20091127-r5931): org.eclipse.persistence.exceptions.ValidationException
Exception Description: The @JoinColumns on the annotated element [field perfilAcao] from the entity class [class modelo.Perfil] is incomplete. When the source entity class uses a composite primary key, a @JoinColumn must be specified for each join column using the @JoinColumns. Both the name and the referencedColumnName elements must be specified in each such @JoinColumn.
at org.eclipse.persistence.exceptions.ValidationException.incompleteJoinColumnsSpecified(ValidationException.java:1808)
at org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.MappingAccessor.getJoinColumnsAndValidate(MappingAccessor.java:499)
at org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.MappingAccessor.getJoinColumns(MappingAccessor.java:456)
at org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.ObjectAccessor.processOneToOneForeignKeyRelationship(ObjectAccessor.java:543)
at org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.ObjectAccessor.processOwningMappingKeys(ObjectAccessor.java:603)
at org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.ManyToOneAccessor.process(ManyToOneAccessor.java:98)
at org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.RelationshipAccessor.processRelationship(RelationshipAccessor.java:546)
at org.eclipse.persistence.internal.jpa.metadata.MetadataProject.processRelationshipAccessors(MetadataProject.java:1085)
at org.eclipse.persistence.internal.jpa.metadata.MetadataProject.processStage3(MetadataProject.java:1364)
at org.eclipse.persistence.internal.jpa.metadata.MetadataProcessor.processORMMetadata(MetadataProcessor.java:462)
at org.eclipse.persistence.internal.jpa.deployment.PersistenceUnitProcessor.processORMetadata(PersistenceUnitProcessor.java:390)
at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.predeploy(EntityManagerSetupImpl.java:940)
at org.eclipse.persistence.internal.jpa.deployment.JPAInitializer.callPredeploy(JPAInitializer.java:88)
at org.eclipse.persistence.jpa.PersistenceProvider.createEntityManagerFactory(PersistenceProvider.java:124)
at org.eclipse.persistence.jpa.PersistenceProvider.createEntityManagerFactory(PersistenceProvider.java:65)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:78)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:54)

O que será que estou fazendo de errado? o mapeamento de um relacionamento composto funciona desta maneira, ou estou surtando? :smiley:

2 Respostas

aconstantino

Tenta colocar um @IdClass(PerfilAcaoPK .class) na classe PerfilAcao

[] ´s

ricardospinoza

Dohko, consegui resolver o problema e nem cheguei a tentar fazer desta forma.
Obrigado por sua ajuda…

Segue a solução:

na classe Perfil modifiquei o trecho de código
de:

@JoinColumn(name = "id_perfil", referencedColumnName = "id_perfil")  
@ManyToOne(fetch = FetchType.LAZY)  
private PerfilAcao perfilAcao;

para:

@OneToMany(mappedBy = "perfil", fetch = FetchType.LAZY)
    private List<PerfilAcao> perfisAcoes;
Criado 31 de março de 2010
Ultima resposta 1 de abr. de 2010
Respostas 2
Participantes 2