问题
I'd like to save rows in a simple table that contains the ids of two other entities. After some tries, I arrived at the following configuration. Spring Boot now correctly creates the table, with column names task_run_id
and project_id
.
But when I call repo.save(participant)
a row is created but both columns contain 0, instead of the required ids. No error is thrown.
What am I doing wrong? Also if there there are some declarations that are unnecessary to achieve a simple save and later query, please tell me.
@Entity
@IdClass(TaskRunParticipant.Id.class)
public class TaskRunParticipant implements Serializable {
@javax.persistence.Id
@Column(name = "run_id")
private long runId;
@javax.persistence.Id
@Column(name = "project_id")
private long projectId;
@OneToOne
@JoinColumn(name="project_id")
@MapsId("project_id")
private Project project;
@OneToOne
@JoinColumn(name="run_id")
@MapsId("run_id")
private TaskRun taskRun;
protected TaskRunParticipant(){}
public TaskRunParticipant(TaskRun run, Project project){
this.taskRun = run;
this.project = project;
}
public Project getProject() { return project; }
public void setProject(Project project) { this.project = project; }
public TaskRun getTaskRun() { return taskRun; }
public void setTaskRun(TaskRun taskRun) { this.taskRun = taskRun; }
protected long getRunId(){ return runId; }
protected long getProjectId(){ return projectId; }
protected void setRunId(long runId){ this.runId = runId; }
protected void setProjectId(long projectId){ this.projectId = projectId; }
public final static class Id implements Serializable {
private long runId;
private long projectId;
public long getRunId() { return runId; }
public void setRunId(long runId) { this.runId = runId; }
public long getProjectId() { return projectId; }
public void setProjectId(long projectId) { this.projectId = projectId; }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Id id = (Id) o;
return runId == id.runId &&
projectId == id.projectId;
}
@Override
public int hashCode() {
return Objects.hash(runId, projectId);
}
}
}
回答1:
It looks like that you can use the MapsId
annotation only with сomposite identifiers mapped by the @EmbeddedId
annotation.
According to the documentation for the MapsId
annotation:
Designates a
ManyToOne
orOneToOne
relationship attribute that provides the mapping for anEmbeddedId
primary key, an attribute within anEmbeddedId
primary key, or a simple primary key of the parent entity. Thevalue
element specifies the attribute within a composite key to which the relationship attribute corresponds.
So, I would suggest you to rewrite your mapping in the following way:
@Embeddable
public class TaskRunParticipantId implements Serializable
{
private Long runId;
private Long projectId;
public TaskRunParticipantId()
{
}
public TaskRunParticipantId(Long runId, Long projectId)
{
this.runId = runId;
this.projectId = projectId;
}
public Long getRunId()
{
return runId;
}
public void setRunId(Long runId)
{
this.runId = runId;
}
public Long getProjectId()
{
return projectId;
}
public void setProjectId(Long projectId)
{
this.projectId = projectId;
}
@Override
public boolean equals(Object o)
{
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TaskRunParticipantId id = (TaskRunParticipantId) o;
return runId == id.runId &&
projectId == id.projectId;
}
@Override
public int hashCode()
{
return Objects.hash(baseModelId, otherEntityId);
}
}
@Entity
public class TaskRunParticipant
{
private TaskRunParticipantId id;
private Project project;
private TaskRun taskRun;
public TaskRunParticipant()
{
id = new TaskRunParticipantId();
}
public TaskRunParticipant(Project project, TaskRun taskRun)
{
this();
this.project = project;
this.taskRun = taskRun;
}
@EmbeddedId
public TaskRunParticipantId getId()
{
return id;
}
public void setId(TaskRunParticipantId id)
{
this.id = id;
}
@OneToOne
@JoinColumn(name="project_id")
@MapsId("projectId")
public Project getProject()
{
return project;
}
public void setProject(Project project)
{
this.project = project;
}
@OneToOne
@JoinColumn(name="run_id")
@MapsId("runId")
public TaskRun getTaskRun()
{
return taskRun;
}
public void setTaskRun(TaskRun taskRun)
{
this.taskRun = taskRun;
}
}
Please note that the value in the MapsId
is the name of appropriate field in the TaskRunParticipantId
class, not the column name.
来源:https://stackoverflow.com/questions/64348075/saving-entity-with-idclass-produces-empty-row