【问题标题】:Saving entity with @IdClass produces empty row使用@IdClass 保存实体会产生空行
【发布时间】:2020-10-14 06:56:25
【问题描述】:

我想将行保存在一个包含其他两个实体 ID 的简单表中。经过一番尝试,我得出了以下配置。 Spring Boot 现在可以正确创建表,列名 task_run_idproject_id

但是当我调用repo.save(participant) 时,会创建一行,但两列都包含 0,而不是所需的 ID。不会抛出任何错误。

我做错了什么? 另外,如果有一些声明对于实现简单的保存和稍后查询是不必要的,请告诉我。

@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);
       }
   }
}

【问题讨论】:

  • 你用的是什么休眠版本?

标签: spring-boot hibernate spring-data-jpa


【解决方案1】:

看来您只能将MapsId 注释与@EmbeddedId annotation 映射的复合标识符一起使用。

根据documentationMapsId注解:

指定一个ManyToOneOneToOne 关系属性,提供EmbeddedId 主键、EmbeddedId 主键内的属性或父实体的简单主键的映射。 value 元素指定关系属性对应的复合键中的属性。

所以,我建议你用以下方式重写你的映射:

@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;
   }
}

请注意MapsId 中的值是TaskRunParticipantId 类中相应字段的名称,而不是列名。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多