Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JPA: Foreign key that is also a primary key mapping

I have been trying to solve this for whole day but no luck! Also i tried to read most of the tutorials on the net but as you all know they all are full of useless examples that do not reflect what you need in the real world.

So here is my situation:

The database:

table: vehicles(vehicleId, brand, model, devYear, regNumber) <-- vehicleId is the PrimaryKey

table: extras(vehicleId, allowSmoke, allowFood, allowDrinks, airConditioner) <-- vehicleId is a PK and a FK.

The point is that if i have a class Vehicle and a class TravelExtras which are mapped to the database i want the Vehicle class to have an attribute TravelExtras travelExtras and get and set methods.

Unfortunatelly no matter what i tried when i try to persist the object in the databse i get various errors.

Here is an illustration:

        EntityManagerFactory emfactory = Persistence.createEntityManagerFactory( "NaStopPU" );
        EntityManager entitymanager = emfactory.createEntityManager( );
        entitymanager.getTransaction( ).begin( );


        TravelExtra travelExtra = new TravelExtra();


        entitymanager.persist(travelExtra);


        Vehicle vehicle = new Vehicle(2L, "10152487958556242", "Mazda", "626", "334343", 2005, 4);  
        vehicle.setTravelExtra(travelExtra);

        entitymanager.persist(vehicle);



        entitymanager.getTransaction().commit();
        entitymanager.close( );

        emfactory.close( );

Any one knows what kind of annotations to use for this One to one case ?

like image 630
Joro Seksa Avatar asked Dec 04 '14 23:12

Joro Seksa


People also ask

Can primary and foreign key be the same?

A primary key is used to ensure data in the specific column is unique. A foreign key is a column or group of columns in a relational database table that provides a link between data in two tables. It uniquely identifies a record in the relational database table.

Can foreign key be primary key JPA?

You can use JPA's @MapsId annotation to tell Hibernate that it shall use the foreign key of an associated entity as the primary key. Let's take a look at a simple example. Each Book has a Manuscript, and each Manuscript belongs to 1 Book. The foreign key of the Book is also the primary key of the Manuscript.

Can a field be a primary key and a foreign key?

Yes, it can.

How does JPA define foreign key?

Implementing With a Foreign Key in JPA. Note that we place the @OneToOne annotation on the related entity field, Address. Also, we need to place the @JoinColumn annotation to configure the name of the column in the users table that maps to the primary key in the address table.


2 Answers

The Java Persistence wikibook has a section called Primary Keys through OneToOne and ManyToOne Relationships which seems to indicate that what you want is possible.

If I'm reading it right, for your case, it would look something like:

class Vehicle {
    @Id
    @Column(name = "EXTRAS_ID")
    private long extrasId;

    @OneToOne(mappedBy="vehicle", cascade=CascadeType.ALL)
    private TravelExtra extras;
}

class TravelExtras {
    @Id
    @Column(name = "VEHICLE_ID")
    private long vehicleId;

    @OneToOne
    @PrimaryKeyJoinColumn(name="VEHICLE_ID", referencedColumnName="EXTRAS_ID")
    private Vehicle vehicle;

    public TravelExtras(Vehicle vehicle) {
        this.vehicleId = vehicle.getId();
        this.vehicle = vehicle;
    }
}

Note that one of your entities will need to make sure it has the same id as the other, which is accomplished in the example by the TravelExtras constructor requiring the Vehicle it is bound to.

like image 50
Chris Rice Avatar answered Nov 02 '22 07:11

Chris Rice


I know this is very old qs, but for completeness of your case you can just have (jpa 2.0)

@Entity
@Data
public class Vehicle implements Serializable{
   @Id
   @GeneratedValue
   private long vehicleId;
   .. //other props
}

@Entity
@Data
public class VehicleExtras implements Serializable{
         @Id
         @OneToOne (cascade = CASCADE.ALL)
         @MapsId
         @JoinColumn(name ="vehicleId")
         private Vehicle vehicle;

         @Column  
         private boolean allowSmoke; 
         ..// other props.
}

should share same pk/fk for VehicleExtra table

like image 37
Sendi_t Avatar answered Nov 02 '22 08:11

Sendi_t