Mapping of primary key as foreign key to another table

12,355

Solution 1

The error message came up because some annotations were wrong.

I changed the primary key of OceanShip from MeansOfTransport to Integer and have now to be careful what I enter there. That's the price I have to pay.

Additionally I changed the annotation where I use OceanShip from this

@ManyToOne
@Column(name = "ocean_ship")
public OceanShip oceanShip;

to this

@ManyToOne
@JoinColumn(name = "ocean_ship", referencedColumnName = "means_of_transport_id")
public OceanShip oceanCarrierShip;

Solution 2

I think your DB model is conceptually not right.

It should be something like this below.

The ocean_ship_id is the PK of the ocean_ship table. And means_of_transport_id from ocean_ship is just a FK to the "base" table means_of_transport.

So I would say you get your DB model right, then worry about the JPA mapping.

CREATE TABLE ocean_ship (
    ocean_ship_id INT PRIMARY KEY NOT NULL,
    means_of_transport_id INT NOT NULL,
    name VARCHAR(45) NOT NULL,
    FOREIGN KEY ( means_of_transport_id ) REFERENCES means_of_transport ( id )
);

Solution 3

See @PrimaryKeyJoinColumn and the ideas given in this thread.

Shared primary key with JPA @MapsId annotation

Might be helpful maybe?

Share:
12,355
nkr
Author by

nkr

Updated on June 30, 2022

Comments

  • nkr
    nkr almost 2 years

    I have a problem regarding a foreign key relationship and its JPA counterpart.

    In the following tables. means_of_transport is a table with a consecutive numbering. The other tables have less entries with a mapping of their primary key as a foreign key to the primary key of means_of_transport. Sadly, I cannot change the data model.

    Table means_of_transport

    CREATE TABLE means_of_transport (
        id INT PRIMARY KEY NOT NULL,
        max_capacity INT
    );
    

    Table ocean_ship

    CREATE TABLE ocean_ship (
        means_of_transport_id INT PRIMARY KEY NOT NULL,
        name VARCHAR(45) NOT NULL,
        FOREIGN KEY ( means_of_transport_id ) REFERENCES means_of_transport ( id )
    );
    CREATE INDEX fk_ship_means_of_transport1_idx ON ocean_ship ( means_of_transport_id );
    

    There are more tables besides ocean_ship with the same key structure but other fields.

    MeansOfTransport.java

    @Entity
    @Table(name = "means_of_transport")
    public class MeansOfTransport extends Model {
        @Id
        public Integer id;
        public Integer maxCapacity;
    }
    

    OceanShip.java

    @Entity
    @Table(name = "ocean_ship")
    public class OceanShip extends Model {
        @Id
        @OneToOne
        @JoinColumn(table = "means_of_transport", referencedColumnName = "id")
        public MeansOfTransport meansOfTransport;
    
        public String name;
    }
    

    Now every time I try to use OceanShip in another JPA class as a field, I get this error: Error reading annotations for models.Classname.

    Am I missing some annotations?

    edit

    Example usage:

    @ManyToOne
    @Column(name = "ocean_ship")
    public OceanShip oceanShip;
    

    Full stack trace:

    play.api.UnexpectedException: Unexpected exception[RuntimeException: Error reading annotations for models.ContainerOrder]
            at play.core.ReloadableApplication$$anonfun$get$1$$anonfun$apply$1$$anonfun$1.apply(ApplicationProvider.scala:150) ~[play_2.10.jar:2.1.5]
            at play.core.ReloadableApplication$$anonfun$get$1$$anonfun$apply$1$$anonfun$1.apply(ApplicationProvider.scala:114) ~[play_2.10.jar:2.1.5]
            at scala.Option.map(Option.scala:145) ~[scala-library.jar:na]
            at play.core.ReloadableApplication$$anonfun$get$1$$anonfun$apply$1.apply(ApplicationProvider.scala:114) ~[play_2.10.jar:2.1.5]
            at play.core.ReloadableApplication$$anonfun$get$1$$anonfun$apply$1.apply(ApplicationProvider.scala:112) ~[play_2.10.jar:2.1.5]
            at scala.util.Either$RightProjection.flatMap(Either.scala:523) ~[scala-library.jar:na]
    Caused by: java.lang.RuntimeException: Error reading annotations for models.ContainerOrder
            at com.avaje.ebeaninternal.server.deploy.parse.ReadAnnotations.readAssociations(ReadAnnotations.java:54) ~[avaje-ebeanorm-server.jar:na]
            at com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager.readDeployAssociations(BeanDescriptorManager.java:1034) ~[avaje-ebeanorm-server.jar:na]
            at com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager.readEntityDeploymentAssociations(BeanDescriptorManager.java:565) ~[avaje-ebeanorm-server.jar:na]
            at com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager.deploy(BeanDescriptorManager.java:252) ~[avaje-ebeanorm-server.jar:na]
            at com.avaje.ebeaninternal.server.core.InternalConfiguration.<init>(InternalConfiguration.java:124) ~[avaje-ebeanorm-server.jar:na]
            at com.avaje.ebeaninternal.server.core.DefaultServerFactory.createServer(DefaultServerFactory.java:210) ~[avaje-ebeanorm-server.jar:na]
    Caused by: java.lang.NullPointerException: null
            at com.avaje.ebeaninternal.server.deploy.BeanTable.createJoinColumn(BeanTable.java:94) ~[avaje-ebeanorm-server.jar:na]
            at com.avaje.ebeaninternal.server.deploy.parse.AnnotationAssocOnes.readAssocOne(AnnotationAssocOnes.java:145) ~[avaje-ebeanorm-server.jar:na]
            at com.avaje.ebeaninternal.server.deploy.parse.AnnotationAssocOnes.parse(AnnotationAssocOnes.java:54) ~[avaje-ebeanorm-server.jar:na]
            at com.avaje.ebeaninternal.server.deploy.parse.ReadAnnotations.readAssociations(ReadAnnotations.java:45) ~[avaje-ebeanorm-server.jar:na]
            at com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager.readDeployAssociations(BeanDescriptorManager.java:1034) ~[avaje-ebeanorm-server.jar:na]
            at com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager.readEntityDeploymentAssociations(BeanDescriptorManager.java:565) ~[avaje-ebeanorm-server.jar:na]