Saving entity with @IdClass produces empty row

别来无恙 提交于 2021-01-29 09:40:02

问题


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 or OneToOne relationship attribute that provides the mapping for an EmbeddedId primary key, an attribute within an EmbeddedId primary key, or a simple primary key of the parent entity. The value 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!