How to correctly describe entities with many-to-many relationship, Spring Boot JPA

Viewed 29

I have those entities:

@Entity
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class Tender {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(nullable = false, updatable = false)
    private Long id;
    private String source;
    private String sourceRefNumber;
    private String link;
    private String title;
    @Column(columnDefinition="TEXT")
    private String description;
    private String field;
    private String client;
    private LocalDate date;
    private LocalDate deadline;
    @ManyToMany
    private List<Cpv> cpv;
}

And CPV:

@Entity
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class Cpv {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String code;
    private String description;
}

Each Tender can have list of Cpv-s. In my DB I have already list of all CPV codes with description, so when I add new Tender to DB, it should add record to tender_cpv table with tender_id and cpv_id. But when I'm using this method in my TenderServiceImpl to set Cpv id-s from DB I got error after that when try to save Tender:

@Override
public Tender addNewTender(Tender tender) {
    if(tender.getCpv() != null) {
        for(Cpv cpv : tender.getCpv()) {
            cpv = cpvRepository.findCpvByCode(cpv.getCode());
        }
    }
    tenderRepository.save(tender);
    return tender;
}

org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.supportportal.domain.Cpv;

I understand that somewhere in the description of the entities a mistake was made, because earlier I did not have a database with all the CPV codes and before saving the tender I saved all the CPVs, but now I need to redo the logic to use the existing CPV database.

Please advise how can I change the entity description.

1 Answers

addNewTender method changes solved my problem:

@Override
public Tender addNewTender(Tender tender) {
    if(tender.getCpv() != null) {
        List<Cpv> dbCpvs = new ArrayList<>();
        for(Cpv cpv : tender.getCpv()) {
            dbCpvs.add(cpvRepository.findCpvByCode(cpv.getCode()));
        }
        tender.setCpv(dbCpvs);
    }
    tenderRepository.save(tender);
    return tender;
}

In order for the existing entities from the database to bind to the new object, we had to first get each of them from the database and bind to the new entity.

Related