Я получаю сообщение об ошибке при попытке обновить список сущностей (Job):
Multiple representations of the same entity [com.introlabsystems.upworkscraper.model.entities.Skill#42] are being merged. Detached: [Skill(id=42, skillName=Web Scraping)]; Detached: [Skill(id=42, skillName=Web Scraping)]
Я думаю, что в случае, если три сущности имеют отношения ManyToMany с сущностью Skill.
@Entity
public class Job {
@Id
@Column(unique = true, nullable = false)
@SerializedName(value = "ciphertext")
private String id;
@Column(length = 2048)
private String title;
@Column(columnDefinition = "TEXT")
@JsonAdapter(value = DescriptionAdapter.class)
private String description;
@SerializedName(value = "subcategory2")
private String category;
@ManyToMany(cascade = {
CascadeType.MERGE
}, fetch = FetchType.EAGER)
@JoinTable(
joinColumns = {@JoinColumn(name = "job_id")},
inverseJoinColumns = {@JoinColumn(name = "skill_id")}
)
@JsonAdapter(value = SkillsAdapter.class)
private Set<Skill> skills;
private String duration;
private String engagement;
@JsonAdapter(value = AmountAdapter.class)
private String amount;
@JsonAdapter(value = AmountAdapter.class)
private String maxAmount;
private String freelancersToHire;
private String enterpriseJob;
private String proposalsTier;
private String stickyLabel;
@SerializedName(value = "tierLabel")
private String tier;
@JsonAdapter(value = DateTimeAdapter.class)
private LocalDateTime createdOn;
@JsonAdapter(value = DateTimeAdapter.class)
private LocalDateTime publishedOn;
@JsonAdapter(value = DateTimeAdapter.class)
private LocalDateTime renewedOn;
private LocalDateTime hiredOn;
@OneToOne(cascade = CascadeType.ALL)
private Contract contract;
@SerializedName(value = "type")
@JsonAdapter(value = JobTypeAdapter.class)
@Enumerated(value = EnumType.STRING)
private JobType jobType;
@Enumerated(value = EnumType.STRING)
private JobStatus jobStatus = JobStatus.OPEN;
private String projectStage;
private String ongoingProject;
private String projectType;
private String finalOutput;
private String Platform;
private String oneTimeProject;
private String jobSuccessScore;
private String includeRisingTalent;
private String englishLevel;
private String upworkHours;
private String freelancerType;
private String preferredLocation;
private String interviewing;
@OneToOne(cascade = CascadeType.ALL)
private PrivateStatus privateStatus;
}
@Data
@Entity
public class Skill {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String skillName;
}
@Data
@Entity
public class Contract {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@JsonAdapter(value = ContractJobIdAdapter.class)
@SerializedName(value = "jobInfo")
private String jobId;
private String totalCharge;
private String totalHours;
@JsonAdapter(value = AmountAdapter.class)
private String rate;
@JsonAdapter(value = DateTimeAdapter.class)
private LocalDateTime startDate;
@JsonAdapter(value = DateTimeAdapter.class)
private LocalDateTime endDate;
@ManyToOne(cascade = CascadeType.MERGE)
@SerializedName(value = "contractorInfo")
private Freelancer freelancer;
@ManyToOne(cascade = CascadeType.ALL)
private Client client;
}
@Data
@Entity
public class Freelancer {
@Id
@SerializedName(value = "ciphertext")
private String id;
@SerializedName(value = "contractorName")
private String name;
@Column(length = 2048)
private String title;
@Column(columnDefinition = "TEXT")
@JsonAdapter(value = DescriptionAdapter.class)
private String description;
@JsonAdapter(value = FreelancerLocationAdapter.class)
private String location;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(
joinColumns = {@JoinColumn(name = "freelancer_id")},
inverseJoinColumns = {@JoinColumn(name = "skill_id")}
)
@JsonAdapter(value = SkillsAdapter.class)
private Set<Skill> skills;
private String hourlyRate;
private String privateFeedbackHireAgain;
private String rating;
private String scores;
private String totalEarnings;
private String totalFeedback;
private String totalFixedJobs;
private String totalHourlyJobs;
private String totalHours;
private String totalJobsWorked;
private String topRatedStatus;
private String successScore;
@OneToMany(cascade = CascadeType.ALL)
private List<ContractHistory> contractHistories;
@ManyToMany(cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
})
@JoinTable(
joinColumns = {@JoinColumn(name = "freelancer_id")},
inverseJoinColumns = {@JoinColumn(name = "agency_id")}
)
private Set<Agency> agency;
}
@Data
@Entity
public class Agency {
@Id
@SerializedName(value = "chipertext")
private String id;
@JsonAdapter(value = AmountAdapter.class)
private String minRate;
@JsonAdapter(value = AmountAdapter.class)
private String maxRate;
private String city;
private String country;
@Column(columnDefinition = "TEXT")
@JsonAdapter(value = DescriptionAdapter.class)
private String description;
private String jobSuccessScore;
private String name;
@Column(length = 2048)
private String title;
private String topRatedStatus;
private String totalEarnings;
private String totalHours;
private String totalJobs;
private String recentEarnings;
private String averageRecentEarnings;
@JsonAdapter(value = DateTimeAdapter.class)
private LocalDateTime memberSince;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(
joinColumns = {@JoinColumn(name = "agency_id")},
inverseJoinColumns = {@JoinColumn(name = "skill_id")}
)
@JsonAdapter(value = SkillsAdapter.class)
private Set<Skill> skills;
}
Я пытаюсь сохранить работу.Перед этим я получаю навыки от работы, агентства, фрилансера, пытаюсь найти их в БД и подставить идентификаторы.
for (Skill skill: skills)
{
Skill skillWithID =
skillDataService.findBySkillName(skill.getSkillName())
.orElseGet(() -> skillDataService.save(skill));
skill.setId(skillWithID.getId());
}