Home > Back-end >  JPA/Hibernate Spring boot-primary key one entity referred as an instance to other entity not working
JPA/Hibernate Spring boot-primary key one entity referred as an instance to other entity not working

Time:10-01

I have generated master tables using liquibase. I have created the corresponding models in spring boot now I want to maintain a relation ship between those models.

I have one table called Vehicle_Type, it is already pre-populated using liquibase.

@Data
@Entity
@Table(name="VEHCILE_TYPE")
public class VehicleType {

    @Id
    private int id;
    
    @Column(name="DISPLAY_NAME")
    private String displayName;
    
    @Column(name="TYPE")
    private String type;
    
    @Column(name="CREATED_DATE")
    private LocalDateTime createdDate;
    
    @Column(name="UPDATED_DATE")
    private LocalDateTime updateDate;
    
    
    
}

now what I want to achieve is, I have one child entity, I have refer the VehicleType instance inside that entity as depicted below

@Data
@Entity
@EqualsAndHashCode(callSuper = true)
@Table(name = "NON_MSIL_VEHICLE_LAYOUT")
public class NonMsilVehicleLayout extends BaseImagesAndLayout {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "NMV_SEQ")
    @SequenceGenerator(sequenceName = "NON_MSIL_VEH_SEQUENCE", allocationSize = 1, name = "NMV_SEQ")
    private int id;

    @OneToOne(cascade=CascadeType.ALL)
    @JoinColumn(name = "VEH_TYPE", referencedColumnName = "id")
    private VehicleType vehicleType;

    public interface VehType {
        String getVehType();
    }

}

The problem is when I tries to save entity NonMsilVehicleLayout, then it tries to first insert the data in VEHICLE_TYPE table also. which should not going to be happen.

I don't want that, I want JPA will pick the correct ID from VEHICLE_TYPE table and place it inside the corresponding table for NonMsilVehicleLayout, because the id of VEHICLE_TYPE table is act as foreign key in Non_Msil_Vehicle_Layout table.

log.info("Inside saveLayout::Start preparing entity to persist");
        String resourceUri = null;
        NonMsilVehicleLayout vehicleLayout = new NonMsilVehicleLayout();
        VehicleType vehicleType=new VehicleType();
        vehicleType.setType(modelCode);
        vehicleLayout.setVehicleType(modelCode);
        vehicleLayout.setFileName(FilenameUtils.removeExtension(FilenameUtils.getName(object.key())));

        vehicleLayout.setS3BucketKey(object.key());

I know I missed something, but unable to figure it out.

CodePudding user response:

You are creating a new VehicleType instance setting only the type field and set the vehicleType field of NonMsilVehicleLayout to that new instance. Since you specified CascadeType.ALL on NonMsilVehicleLayout#vehicleType, this means to Hibernate, that it has to persist the given VehicleType, because the instance has no primary key set.

I guess what you rather want is this code:

vehicleLayout.setVehicleType(
    entitManager.createQuery("from VehicleType vt where vt.type = :type", VehicleType.class)
        .setParameter("type", typeCode)
        .getSingleResult()
);

This will load the VehicleType object by type and set that object on NonMsilVehicleLayout#vehicleType, which will then cause the foreign key column to be properly set to the primary key value.

CodePudding user response:

Finally, after some workaround, I got the mistake, the column name attribute was incorrect, so I made it correct and remove the referencedColumn and Cascading.

Incorrect:

@OneToOne(cascade=CascadeType.ALL)
    @JoinColumn(name = "VEH_TYPE", referencedColumnName = "id")
    private VehicleType vehicleType;

Correct:

 @OneToOne
    @JoinColumn(name = "VEHICLE_TYPE")
    private VehicleType vehicleTypes;

also I have added the annotation @Column in the referende entity VehicleImage

public class VehicleType {

    @Id
    @Column(name = "ID") // added this one
    private int id;
 }

That bit workaround solved my problem, now I have achieved what I exactly looking for.

  • Related