Home > Software design >  JPA identifier of an instance was altered from 'X' to null
JPA identifier of an instance was altered from 'X' to null

Time:01-05

Issue

This is my first time working with JPA. I have 2 entities: Component and Manufacturer, which are in ManyToOne relation. The Manufacturer's ID is the foreign key in Component. Only the foreign key should be deleted. When I try to set a component's ID to null and save it, the following exception occurs:

"identifier of an instance of spring.model.Manufacturer was altered
 from 1 to null; nested exception is org.hibernate.HibernateException: identifier of an 
instance of spring.model.Manufacturer was altered from 1 to null",

ER Diagram

enter image description here

Models

BaseEntity

@Data
@MappedSuperclass
public class BaseEntity implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    protected Long id;
}

Component

@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "Components")
public class Component extends BaseEntity {

    @Column(nullable = false)
    private String type;

    @Column(nullable = false)
    private String name;

    @Column(nullable = false)
    private Double price;

    @Column(nullable = false, length = 2048)
    private String description;

    @Column(nullable = false)
    private Integer rating;

    @ManyToOne()
    @JoinColumn(name = "manufacturerId")
    private Manufacturer manufacturer;
}

Manufacturer

@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "Manufacturers")
public class Manufacturer extends BaseEntity {

    @Column(nullable = false, unique = true)
    private String name;

    @Column(nullable = false)
    private Integer foundingYear;

    @Column(nullable = false)
    private Double revenue;

    @OneToMany(mappedBy = "manufacturer", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<Component> components = new ArrayList<>();
}

Current code

@DeleteMapping
@ResponseStatus(HttpStatus.NO_CONTENT)
public void deleteComponentManufacturer(@PathVariable("componentId") Long id) {
    Optional<Component> component = componentDao.findById(id);
    if (component.isEmpty()) {
        throw new BadRequestException("Could not delete component's (ID: "   id   ") manufacturer");
    }
    if (component.get().getManufacturer() == null) {
        throw new BadRequestException("Component with ID: "   id   " has no manufacturer");
    }
    component.get().getManufacturer().setId(null);
     componentDao.save(component.get());              // Error is thrown here
}

CodePudding user response:

You are setting the manufacturer's id from whatever it was to null here:

component.get().getManufacturer().setId(null);

When you call .getManufacturer() you are getting the actual entity linked to the record in the manufacturer table. When you call .setId(null) on that object, you are modifying the manufacturer.

I suspect what you are trying to do is disassociate the component from the manufacturer, so that on the component record, the manufacturerid is null. To do that, you need this:

component.get().setManufacturer(null);
  • Related