使用@IdClass 保存实体会产生空行 [英] Saving entity with @IdClass produces empty row
问题描述
我想将行保存在一个包含其他两个实体的 ID 的简单表中.经过一些尝试,我得到了以下配置.Spring Boot 现在可以正确创建表,列名为 task_run_id
和 project_id
.
但是当我调用 repo.save(participant)
时,会创建一行,但两列都包含 0,而不是所需的 id.不会抛出任何错误.
我做错了什么?另外如果有一些不需要实现简单保存和后续查询的声明,请告诉我.
@Entity@IdClass(TaskRunParticipant.Id.class)公共类 TaskRunParticipant 实现了 Serializable {@javax.persistence.Id@Column(name = "run_id")私人长期运行Id;@javax.persistence.Id@Column(name = "project_id")私人长项目Id;@OneToOne@JoinColumn(name="project_id")@MapsId("project_id")私人项目项目;@OneToOne@JoinColumn(name="run_id")@MapsId("run_id")私人任务运行任务运行;受保护的 TaskRunParticipant(){}公共TaskRunParticipant(TaskRun运行,项目项目){this.taskRun = 运行;this.project = 项目;}公共项目 getProject() { 返回项目;}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;}公共最终静态类 ID 实现可序列化 {私人长期身份;私人长项目Id;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;}@覆盖公共布尔等于(对象 o){if (this == o) 返回真;if (o == null || getClass() != o.getClass()) 返回假;id id = (Id) o;返回 runId == id.runId &&projectId == id.projectId;}@覆盖公共 int hashCode() {返回 Objects.hash(runId, projectId);}}}
看起来您只能将 MapsId
注释与 @EmbeddedId
映射的复合标识符一起使用注释.>
根据文档MapsId
注释:
指定一个 ManyToOne
或 OneToOne
关系属性,为 EmbeddedId
主键提供映射,EmbeddedId
主键,或父实体的简单主键.value
元素指定关系属性对应的组合键中的属性.
因此,我建议您按以下方式重写映射:
@Embeddable公共类 TaskRunParticipantId 实现了可序列化{私人长期运行ID;私人长项目ID;公共 TaskRunParticipantId(){}public TaskRunParticipantId(Long runId, Long projectId){this.runId = runId;this.projectId = projectId;}公共长 getRunId(){返回运行ID;}public void setRunId(Long runId){this.runId = runId;}公共长 getProjectId(){返回项目ID;}public void setProjectId(Long projectId){this.projectId = projectId;}@覆盖公共布尔等于(对象 o){if (this == o) 返回真;if (o == null || getClass() != o.getClass()) 返回假;TaskRunParticipantId id = (TaskRunParticipantId) o;返回 runId == id.runId &&projectId == id.projectId;}@覆盖公共 int hashCode(){返回 Objects.hash(baseModelId, otherEntityId);}}@实体公共类 TaskRunParticipant{私有 TaskRunParticipantId id;私人项目项目;私人任务运行任务运行;公共 TaskRunParticipant(){id = new TaskRunParticipantId();}公共TaskRunParticipant(项目项目,TaskRun taskRun){这();this.project = 项目;this.taskRun = taskRun;}@EmbeddedId公共 TaskRunParticipantId getId(){返回标识;}public void setId(TaskRunParticipantId id){this.id = id;}@OneToOne@JoinColumn(name="project_id")@MapsId("projectId")公共项目 getProject(){回归项目;}public void setProject(项目项目){this.project = 项目;}@OneToOne@JoinColumn(name="run_id")@MapsId("runId")公共 TaskRun getTaskRun(){返回任务运行;}public void setTaskRun(TaskRun taskRun){this.taskRun = taskRun;}}
请注意,MapsId
中的值是 TaskRunParticipantId
类中相应字段的名称,而不是列名称.
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);
}
}
}
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.
这篇关于使用@IdClass 保存实体会产生空行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!