You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@openjpa.apache.org by Mansour Al Akeel <ma...@gmail.com> on 2014/07/12 13:03:07 UTC

Problem creating table with @IdClass an foreign keys constraints

Hello all,

To demonstrate the problem and make it easier to get help, I have created
an application here:

https://github.com/malakeel/jpa-id-class-example


This application is to create tables with constrains from JPA entities.
Tables are created, however I am unable to generate
the foreign key constrains.

Here's the description of the entities. We have the Services Entity, with
fields relates the service provider to the
client, and the service type. The Service Entity has its primary keys
(service provider and client). Both are Person(s).

When this application is run using @IdClass(ServicePK.class), I get the
exception:

<openjpa-2.3.0-r422266:1540826 fatal user error>
org.apache.openjpa.persistence.ArgumentException: The id class specified by
type "class com.example.Service" does not match the primary key fields of
the class.  Make sure your identity class has the same primary keys as your
persistent type, including pk field types. Mismatched property: "client"
    at
org.apache.openjpa.meta.ClassMetaData.validateAppIdClassPKs(ClassMetaData.java:2225)
    at
org.apache.openjpa.meta.ClassMetaData.validateAppIdClass(ClassMetaData.java:2099)
    at
org.apache.openjpa.meta.ClassMetaData.validateIdentity(ClassMetaData.java:2035)
    at
org.apache.openjpa.meta.ClassMetaData.validateMeta(ClassMetaData.java:1947)
    at
org.apache.openjpa.meta.ClassMetaData.resolve(ClassMetaData.java:1808)

Please note that the Composite Key has objects as keys.

For convenience I created another @IdClass called (ServicePK_Simple.java).
We can change the @IdClass(ServicePK.class) to
@IdClass(ServicePK_Simple.class).

This class has the fields as Strings. If we use this class as the PK for
service, then the tables are generated but without FK constrains.
For example on postgresql, this is the "create table sql" statement:

CREATE TABLE service
(
  client_id character varying(255) NOT NULL,
  ser_provider_id character varying(255) NOT NULL,
  type_id character varying(255),
  CONSTRAINT service_pkey PRIMARY KEY (client_id, ser_provider_id)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE service
  OWNER TO postgres;

CREATE INDEX i_service_type
  ON service
  USING btree
  (type_id COLLATE pg_catalog."default");


I have tested it with hibernate as well, to make sure I am not missing
something. To see the test results with hibernate, please change the
<provider> class in persistence.xml. Hibernate is generating the table with
correct constraints:


CREATE TABLE service
(
  ser_provider_id character varying(255) NOT NULL,
  client_id character varying(255) NOT NULL,
  type_id character varying(255),
  CONSTRAINT service_pkey PRIMARY KEY (client_id, ser_provider_id),
  CONSTRAINT fkd97c5e956f35ba95 FOREIGN KEY (client_id)
      REFERENCES person (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT fkd97c5e95b83f253e FOREIGN KEY (type_id)
      REFERENCES servicetype (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT fkd97c5e95e71b3950 FOREIGN KEY (ser_provider_id)
      REFERENCES person (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITH (
  OIDS=FALSE
);
ALTER TABLE service
  OWNER TO postgres;


What do I need to do to get this to work with OpenJPA ?

Thank you.

Re: Problem creating table with @IdClass an foreign keys constraints

Posted by Mansour Al Akeel <ma...@gmail.com>.
I found the answer. It was my fault. Here's what I have, in case
someone else faced the same problem.

>From JPA specs, section "2.4.1.1 Specification of Derived Identities":

============================================================
If an Id attribute in the entity is a many-to-one or one-to-one
relationship to a parent entity, the corresponding attribute in the id
class must be of the same Java type as the
id class or embedded id of the parent entity (if the parent entity has
a composite primary key) or the type of the Id attribute of the parent
entity (if the parent entity has a
simple primary key).
============================================================

In other words, if the entity has a field called "client" and type
"Person" , then in the composite primary key, the filed in the PK
class needs to be called "client", and the type is the same type of
the primary key of the "Person" class. In the case the primary key for
Person.class is String, so client in the composite PK class should be
type String.
Once this is done, we need to add to persistence.xml

            <property name="openjpa.jdbc.MappingDefaults"
value="ForeignKeyDeleteAction=restrict,JoinForeignKeyDeleteAction=restrict"
/>

, as explained in http://openjpa.apache.org/faq.html  (by the way the
anchor at the top of the page is missing  "Why OpenJPA is not creating
foreign key constraints on the database tables?")

The confusing part was that hibernate worked fine with Other object
Types in the PK class !
Anyhow, problem solved (for now).