41
votes

I have been reading a lot about @JoinColumn but I still don't get the idea behind it.

Patient Table

CREATE TABLE patient (
patient_id BIGINT NOT NULL,
first_name VARCHAR(255) NOT NULL,
last_name VARCHAR(255) NOT NULL,
PRIMARY KEY(patient_id));

Vehicle Table

CREATE TABLE vehicles (
patient_id BIGINT NOT NULL,
vehicle_id BIGINT NOT NULL,
vehicle_manufacturer VARCHAR(255),
PRIMARY KEY (vehicle_id),
CONSTRAINT patienthasmanyvehicle FOREIGN KEY(patient_id) REFERENCES patient(patient_id));

Patient Class

@OneToMany(mappedBy = "patient")
    private Collection<Vehicle> patientVehicles = new ArrayList<Vehicle>();

Vehicle Class

@ManyToOne
@JoinColumn(name="patient_id")
private Patient patient;

I'm confused on how the Vehicle class part, what is the relationship between

Vehicle Class ---- Entity
@JoinColumn(name="patient_id") ---- annotation
private Patient patient ----field

Does it say; The Vehicle Entity has a Foreign Key to Patient entity named patient_id. Add the patient_id as a column in the Vehicle Entity table

Do the name parameter of the JoinColumn should always be a Foreign Key or Primary Key?

I have been reading this but I'm still confuse. JPA JoinColumn vs mappedBy

5

5 Answers

64
votes

A unidirectional association via a join table

@Entity
class Patient {

    @OneToMany
    private Collection<Vehicle> vehicles = new ArrayList<Vehicle>();

}

@Entity
class Vehicle {

}

A bidirectional association via a join table

@Entity
class Patient {

    @OneToMany
    private Collection<Vehicle> vehicles = new ArrayList<Vehicle>();

}

@Entity
class Vehicle {

    @ManyToOne(fetch = FetchType.LAZY)
    private Patient patient;

}

A unidirectional association via a foreign key

@Entity
class Patient {

    @OneToMany
    @JoinColumn
    private Collection<Vehicle> vehicles = new ArrayList<Vehicle>();

}

@Entity
class Vehicle {

}

A bidirectional association via a foreign key

@Entity
class Patient {

    @OneToMany(mappedBy = "patient")
    private Collection<Vehicle> vehicles = new ArrayList<Vehicle>();

}

@Entity
class Vehicle {

    @ManyToOne(fetch = FetchType.LAZY)
    private Patient patient;

}

A bidirectional association via a foreign key with a foreign column name specification

@Entity
class Patient {

    @OneToMany(mappedBy = "patient")
    private Collection<Vehicle> vehicles = new ArrayList<Vehicle>();

}

@Entity
class Vehicle {

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="patient_id")
    private Patient patient;

}

This is the basic starting point of using @JoinColumn.

To verify that the foreign key(patient_id in the Vehicle table) is really mapped in the patients table you can use @JoinColumn(nullable = false)

@Entity
class Vehicle {

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="patient_id", nullable = false)
    private Patient patient

}
5
votes

The join column is declared with the @JoinColumn annotation which looks like the @Column annotation. It has one more parameters named referencedColumnName. This parameter declares the column in the targeted entity that will be used to the join.

In a bidirectional relationship, one of the sides (and only one) has to be the owner: the owner is responsible for the association column(s) update. To declare a side as not responsible for the relationship, the attribute mappedBy is used. mappedBy refers to the property name of the association on the owner side.

Here is Sample code :

EntityOne : 
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "TEST_ID")
    private EntityTwo entityTwo;

EntityTwo : 
      // bi-directional many-to-one association to EntityOne Here TEST_ID is the Primary key
    @OneToMany(mappedBy = "entityTwo")
    private List<EntityOne> entityOne;
3
votes

Vehicle Class ---- Entity @JoinColumn(name="patient_id") ---- annotation private Patient patient ----field

Above code will generate a column patient_id (a foreign key) in Vehicle class which will point to Patient Class primary key.

MappedBy - This attribute tells us that this relation will be managed by Vehicle class. Example. If we insert a vehicle, then two SQL will be injected if cascadetype is all/save. 1st SQL will inject details in Patient table and 2nd SQL will inject vehicle details in vehicle table with patient_id column of Vehicle column pointing to Patient tuple inserted.

1
votes

The table in which join column will be found depends upon context.

  • If the join is for a OneToOne or ManyToOne mapping using a foreign key mapping strategy, the foreign key column is in the table of the source entity or embeddable.

  • If the join is for a unidirectional OneToMany mapping using a foreign key mapping strategy, the foreign key is in the table of the target entity.

  • If the join is for a ManyToMany mapping or for a OneToOne or bidirectional ManyToOne/OneToMany mapping using a join table, the foreign key is in a join table.

  • If the join is for an element collection, the foreign key is in a collection table.

0
votes

Why is that the patient_id (generated column which is a FK) in the Vehicle Table doesn't have any value when I run my code?

All @JoinColumn does is to specify a column for joining an entity association or element collection. Since you have made @JoinColumn associated with Patient class object, that's why foreign key is created on Patient table.

For more please refer https://docs.jboss.org/hibernate/jpa/2.1/api/javax/persistence/JoinColumn.html