2010-04-28 32 views
9

Estoy trabajando en un proyecto de JPA. Necesito usar un mapeo @OneToMany en una clase que tiene tres claves principales. Puede encontrar los errores y las clases después de esto.JPA @OneToMany y compuesto PK

javax.persistence.PersistenceException: No Persistence provider for EntityManager named JTA_pacePersistence: Provider named oracle.toplink.essentials.PersistenceProvider threw unexpected exception at create EntityManagerFactory: 
javax.persistence.PersistenceException 
javax.persistence.PersistenceException: Exception [TOPLINK-28018] (Oracle TopLink Essentials - 2.0.1 (Build b09d-fcs (12/06/2007))): oracle.toplink.essentials.exceptions.EntityManagerSetupException 
Exception Description: predeploy for PersistenceUnit [JTA_pacePersistence] failed. 
Internal Exception: Exception [TOPLINK-7220] (Oracle TopLink Essentials - 2.0.1 (Build b09d-fcs (12/06/2007))): oracle.toplink.essentials.exceptions.ValidationException 
Exception Description: The @JoinColumns on the annotated element [private java.util.Set isd.pacepersistence.common.Action.permissions] from the entity class [class isd.pacepersistence.common.Action] 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 referenceColumnName elements must be specified in each such @JoinColumn. 
    at oracle.toplink.essentials.internal.ejb.cmp3.EntityManagerSetupImpl.predeploy(EntityManagerSetupImpl.java:643) 
    at oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider.createEntityManagerFactory(EntityManagerFactoryProvider.java:196) 
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:110) 
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:83) 
    at isd.pacepersistence.common.DataMapper.(Unknown Source) 
    at isd.pacepersistence.server.MainServlet.getDebugCase(Unknown Source) 
    at isd.pacepersistence.server.MainServlet.doGet(Unknown Source) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:718) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:831) 
    at org.apache.catalina.core.ApplicationFilterChain.servletService(ApplicationFilterChain.java:411) 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:290) 
    at org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java:271) 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:202) 

Aquí está el código fuente de mis clases:

Acción:

@Entity 
@Table(name="action") 
public class Action { 

    @Id 
    @GeneratedValue(strategy=GenerationType.IDENTITY) 
    private int num; 

    @ManyToOne(cascade= { CascadeType.PERSIST, CascadeType.MERGE, 
     CascadeType.REFRESH }) 
    @JoinColumn(name="domain_num") 
    private Domain domain; 

    private String name; 
    private String description; 

    @OneToMany 
    @JoinTable(name="permission", joinColumns= { @JoinColumn(name="action_num", referencedColumnName="action_num", nullable=false, updatable=false) }, inverseJoinColumns= { @JoinColumn(name="num") }) 
    private Set<Permission> permissions; 

    public Action() { 
    } 

Permiso:

@SuppressWarnings("serial") 
@Entity 
@Table(name="permission") 
public class Permission implements Serializable { 

    @EmbeddedId 
    private PermissionPK primaryKey; 

    @ManyToOne 
    @JoinColumn(name="action_num", insertable=false, updatable=false) 
    private Action action; 

    @ManyToOne 
    @JoinColumn(name="entity_num", insertable=false, updatable=false) 
    private isd.pacepersistence.common.Entity entity; 

    @ManyToOne 
    @JoinColumn(name="class_num", insertable=false, updatable=false) 
    private Clazz clazz; 

    private String kondition; 

    public Permission() { 
    } 

PermissionPK:

@SuppressWarnings("serial") 
@Entity 
@Table(name="permission") 
public class Permission implements Serializable { 

    @EmbeddedId 
    private PermissionPK primaryKey; 

    @ManyToOne 
    @JoinColumn(name="action_num", insertable=false, updatable=false) 
    private Action action; 

    @ManyToOne 
    @JoinColumn(name="entity_num", insertable=false, updatable=false) 
    private isd.pacepersistence.common.Entity entity; 

    @ManyToOne 
    @JoinColumn(name="class_num", insertable=false, updatable=false) 
    private Clazz clazz; 

    private String kondition; 

    public Permission() { 
    } 
+3

Parece que has duplicó el código fuente 'permiso' en la lista del 'PermissionPK' . – Henry

Respuesta

1

El mensaje de error parece bastante claro: debe declarar las tres columnas de su PK compuesto como @JoinColum y name y referenceColumnName se deben especificar para cada una. No he probado el mapeo pero trata de esto:

@OneToMany 
@JoinTable(name="permission", joinColumns= { 
    @JoinColumn(name="col1", referencedColumnName="col1", nullable=false, updatable=false), 
    @JoinColumn(name="col2", referencedColumnName="col2", ...), 
    @JoinColumn(name="col3", referencedColumnName="col3", ...) 
}, inverseJoinColumns= { @JoinColumn(name="num") }) 
private Set<Permission> permissions; 
+1

Gracias por su respuesta, pero traté de declarar las tres columnas de mi PK compuesto como @JoinColum y me dio un error también. El error fue el opuesto al primero. Solicitó declarar una sola clave principal y no tres utilizando @JoinColumn. De todos modos, ¡encontré la solución! Voy a publicar una respuesta con un ejemplo de código ahora mismo. –

11

Buenos días,

Después de un largo día en busca cómo APP y @OneToMany trabaja con PK compuesto, he encontrado una solución. Para que funcione, utilicé el parámetro mappedBY de @OneToMany. Como puede ver en el ejemplo del código, mapeé el conjunto de permisos con la acción de atributo de la clase Permiso. ¡Y eso es! ¡Simple cuando lo sabes!

FF

Acción Clase:

@Entity 
@Table(name="action") 
public class Action { 

    @Id 
    @GeneratedValue(strategy=GenerationType.IDENTITY) 
    private int num; 

    @ManyToOne(cascade= { CascadeType.PERSIST, CascadeType.MERGE, 
     CascadeType.REFRESH }) 
    @JoinColumn(name="domain_num") 
    private Domain domain; 

    private String name; 
    private String description; 

    @OneToMany(mappedBy="action") 
    private Set<Permission> permissions; 

Clase Permiso

@SuppressWarnings("serial") 
@Entity 
@Table(name="permission") 
public class Permission implements Serializable { 

    @EmbeddedId 
    private PermissionPK primaryKey; 

    @ManyToOne 
    @JoinColumn(name="action_num", insertable=false, updatable=false) 
    private Action action; 
Cuestiones relacionadas