Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JPA & Hibernate - Composite primary key with foreign key

So I have two tables which I would like to have in Spring memory to query. I have successfully managed to model the 'Drugs' table in an entiry called Medicine, however now need to model the 'drugInteraction' table - which will have the combination of drug_id(PK called id in medicine table), and the drug_name in the drugInteraction table, as a combined primary key.

Schemas as used in python:

cursor.execute("CREATE TABLE drugs(id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255), description TEXT, toxicity TEXT)")


cursor.execute("CREATE TABLE drugInteractions (drug_id INT NOT NULL, name VARCHAR(90), description TEXT, PRIMARY KEY(drug_id, name), FOREIGN KEY (drug_id) REFERENCES drugs (id))")

Some example data for the drugInteractions table:


drug_id     name       description

1       "Abciximab"         "The risk or severity of bleeding can be increased when Abciximab is combined with Lepirudin."
1       "Aceclofenac"        "The risk or severity of bleeding and hemorrhage can be increased when Aceclofenac is combined with Lepirudin."
1.      "Acemetacin"         "The risk or severity of bleeding and hemorrhage can be increased when Lepirudin is combined with Acemetacin."

Some example data for the drugs table:

id.       name.       description

1       "Lepirudin"      "Lepirudin is identical to...."
2       "Cetuximab"      "Cetuximab is an epidermal growth..."

Here's what I have for the Medicine.java:

package com.example.configbackendspring;

import net.minidev.json.JSONObject;

import javax.persistence.*;

@Entity
@Table(name = "drugs")
public class Medicine {
    @Id
    @GeneratedValue
    @Column(name = "id")
    private Integer id;
    @Column(name = "name")
    private String name;
    @Column(name = "description")
    private String description;
    @Column(name = "toxicity")
    private String toxicity;

    public Medicine(int id, String name, String description, String toxicity) {
        this.id=id;
        this.name=name;
        this.description=description;
        this.toxicity=toxicity;
    }


    public Medicine(){}


    public int getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getToxicity() {
        return toxicity;
    }

    public void setToxicity(String toxicity) {
        this.toxicity = toxicity;
    }

    public JSONObject toJSONObject(){
        JSONObject object = new JSONObject();
        JSONObject medicineObject = new JSONObject();
        medicineObject.appendField("name", this.name);
        medicineObject.appendField("description", this.description);
        medicineObject.appendField("toxicity", this.toxicity);
        medicineObject.appendField("id", this.id);
        object.appendField("medicine", medicineObject);
        return object;

    }
}

And this is what I have for the drugInteraction.java ...which does not work

package com.example.configbackendspring;

import net.minidev.json.JSONObject;

import javax.persistence.*;
import javax.resource.cci.Interaction;
import java.io.Serializable;


@Entity
@Table(name = "drugInteractions")
public class DrugInteraction {


    @EmbeddedId
    private InteractionId interactionId;

    @Column(name = "description")
    private String description;


    public DrugInteraction(int drug_id, String name, String description) {
        this.interactionId.drug_name = name;
        this.interactionId.drug_id = drug_id;
        this.description=description;

    }


    public DrugInteraction(){}


    public Integer getId() {
        return interactionId.drug_id;
    }


    public String getName() {
        return interactionId.drug_name;
    }


    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }


    public JSONObject toJSONObject(){
        JSONObject object = new JSONObject();
        JSONObject interactionObject = new JSONObject();
        interactionObject.appendField("name", interactionId.drug_name);
        interactionObject.appendField("description", this.description);
        interactionObject.appendField("drug_id", interactionId.drug_id);
        object.appendField("drugInteraction", interactionObject);
        return object;

    }
}

This is InteractionId.java

package com.example.configbackendspring;

import lombok.*;

import java.io.Serializable;

@RequiredArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
@EqualsAndHashCode
public class InteractionId implements Serializable
{

//    public InteractionId(int drug_id, String drug_name){
//        this.drug_id=drug_id;
//        this.drug_name=drug_name;
//
//    }


    @NonNull
    public int drug_id;

    @NonNull
    public String drug_name;
}


My current issue is that I can't figure out how to link the foreign key id in drugs with the composite key. The above code is compiling but the database is empty so the import must be failing somewhere

Please, can someone advise as to how I would change the files to model the above behaviour? I am having trouble figuring out how I would model the composite ID with foreign key

like image 736
Ariane Avatar asked Oct 23 '19 16:10

Ariane


People also ask

What is JPA?

The Java™ Persistence API (JPA) provides a mechanism for managing persistence and object-relational mapping and functions since the EJB 3.0 specifications. The JPA specification defines the object-relational mapping internally, rather than relying on vendor-specific mapping implementations.

What is JPA and why it is used?

JPA stands for Java Persistence API (Application Programming Interface). It was initially released on 11 May 2006. It is a Java specification that gives some functionality and standard to ORM tools. It is used to examine, control, and persist data between Java objects and relational databases.

What is JPA in Java Spring?

JPA is a specification which specifies how to access, manage and persist information/data between java objects and relational databases. It provides a standard approach for ORM, Object Relational Mapping. Spring Boot provides a seemless integration with JPA.

What is JPA in Java example?

The Java Persistence API (JPA) is one possible approach to ORM. Via JPA the developer can map, store, update and retrieve data from relational databases to Java objects and vice versa. JPA can be used in Java-EE and Java-SE applications. JPA is a specification and several implementations are available.


1 Answers

You have multiple things wrong. If you are using @EmbeddedId then the you ID class needs to be an embeddable.

@Embeddable
public class InteractionId {
    @Column(name="name")
    String name;
    Long drugId; //type should be same as for ID field on Medicine

    //equals and hashcode etc.
}

You also need a relationship from DrugInteraction to Medicine annotated with MapsId:

@Entity
@Table(name = "drugInteractions")
public class DrugInteraction {

    @EmbeddedId
    private InteractionId interactionId;

    @MapsId("drugId")//value corresponds to property in the ID class
    @ManyToOne
    @JoinColumn(name = "drug_id")
    private Medicine medicine;
}

To save a new instance:

DrugInteraction di = new DrugInteraction();
Medicine medicine = //an existing medicine
di.setName("Some Name");
di.setMedicine(medicine);
//save

As an alternative, can also do this using an IDClass rather than EmbeddedId:

//not an embeddable
public class InteractionId {
    String name;
    Long drugId; //type should be same as for ID field on Medicine

    //equals and hashcode etc.
}

and change the mappings:

@Entity
@Table(name = "drugInteractions")
@IdClass(InteractionId.class) //specify the ID class
public class DrugInteraction {

    @Id
    private String name;

    @Id
    @ManyToOne
    @JoinColumn(name = "drug_id")
    private Medicine medicine;
}
like image 185
Alan Hay Avatar answered Nov 15 '22 04:11

Alan Hay