尝试更新实体列表(作业)时出现错误:
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)]
我认为是三个实体与Skill实体具有ManyToMany关系的情况。
@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;
}
我试图保存工作。在此之前,我从工作,代理,自由职业者那里获得了技能,试图在数据库中搜索这些技能并替换ID。
for (Skill skill: skills) { Skill skillWithID = skillDataService.findBySkillName(skill.getSkillName()) .orElseGet(() -> skillDataService.save(skill)); skill.setId(skillWithID.getId()); }
答案 0 :(得分:1)
已更改
CascadeType.MERGE
到
CascadeType.PERSIST,
CascadeType.DETACH,
CascadeType.REFRESH,
CascadeType.REMOVE
它有效
答案 1 :(得分:0)
您面临这个问题是因为您正在将对象添加到已经可用的列表中。同时使用 oneToMany 映射执行保存操作
现在从级联中删除 CascadeType.MERGE 是一种解决方案,但不是最好的解决方案,因为从级联中删除 MERGE 后,您将永远无法更新映射对象
如果您还想对映射对象执行更新操作和保存操作,那么在将映射对象添加到列表/集合之前,只需在列表中检查/搜索对象,如果映射对象在列表中可用,则执行操作在那个特定的对象上。