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.