java @多列上的OneToMany

qxgroojn  于 2023-04-19  发布在  Java
关注(0)|答案(1)|浏览(109)

我在两个类之间的@oneToMany关系上有问题:我的第一堂课是

@Data
@Entity
@Table(name = "job")
public class Jobs {

    @Id
    @Column
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer jobId;

    @OneToMany
    private List<JobsStatus> jobStatus;
}

和我的工作状态类

@Data
@Entity
@Table(name = "job_status")
public class JobsStatus {

    @Id
    @Column(columnDefinition = "VARCHAR(20)")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private String jobStatus;

    @Column(name="sysdate")
    private Date sysDate;
}

JobsStatus是数据库中的一个静态表,这是我在表上选择时的结果
已完成空值
错误为空
插入空值
处理空
已验证空值
验证无效
这是可以的,因为日期应该为空
在我运行我的代码后,我可以看到我的数据库中的关系表(job_job_status),并得到以下结果
irjobs_job_id工作状态工作状态
1个插入
1处理
1个已确认
1验证
这是可以的,但是,每次我更新我的作业类时,我都需要在job_job_status表中看到sysDate,如下所示:
jobs_job_id job_status_job_status sysDate
1例插入日期:2023年4月14日
1处理04/14/2023
1个已确认04/14/2023
1个验证日期:2023年4月14日
我只需要在关系表(job_job_status)上再增加一列sysDate
我试着这样更新:

JobsStatus jobStatus = new IRJobsStatus();
jobStatus.setJobStatus("INSERTED");
jobStatus.setSysDate(new java.sql.Date(new java.util.Date().getTime()));
jobStatusList.add(jobStatus);

有人能帮帮我吗?

nqwrtyyt

nqwrtyyt1#

JPA通过实体对持久状态进行建模。您不能用它们自己的状态来标记关系。如果您发现自己想要这样做,那么这就是您需要插入额外实体的信号。
在对JPA 2.0 many-to-many with extra column的回答中描述了用于此的典型过程。相同的方法可以用于一对多,其中关系通过连接表建模,但是如果关系是***一***对多,则数据通常可以记录在“多”侧的实体中。因为这些中的每一个无论如何都是“一”侧上的恰好一个实体所特有/所拥有的。
至于你提出的具体问题:
JobsStatus是数据库中的静态表
我的意思是这个表永远不会被修改。它只用于枚举允许的状态代码,如“COMPLETED”。(更常见的变体还将这些代码与代理主键关联,但这不是必需的。)
但是如果它从来没有被修改过,那么这个表的sysDate列对于所有行都是空的就没有用了。这不携带任何信息,而且永远不会携带任何信息,因为这些行不应该被修改。此外,如果数据库必须支持在同一时间不同作业的相同状态的日期,那么这个列无论如何都是不够的。
我试着这样更新:

JobsStatus jobStatus = new IRJobsStatus();
jobStatus.setJobStatus("INSERTED");
jobStatus.setSysDate(new java.sql.Date(new java.util.Date().getTime()));
jobStatusList.add(jobStatus);

如果你通过jobStatus.setSysDate()设置了一个实体属性,那么你应该期望任何持久化的表示都存储在实体的表中。此外,如果你创建了一个 new 实体(即JobStatus)并持久化它,那么你应该期望在该实体的表中有一个新的行。这不适合我对“静态”表的理解。
总的来说,我认为这正是链接问题中描述的情况,但你从不同的Angular 来看待它。与Job s具有一对多关系的东西不是状态,而是状态 * 日期 *。而且,我假设,可能有许多状态日期(对于不同的工作)与相同的状态。因此,多重性是:

Job (1) --- (many) JobStatusDate (many) --- (1) JobStatus

如果折叠它以查看Job:JobStatus多重性,则它是多对多的。
我希望我的方向已经很清楚了。你需要引入一个新的实体来携带每个工作的各种状态的日期。这可以有多种结构,但最符合你的数据库设计的是这样的:

@Entity
public class Job {
    @Id
    private Integer jobId;

    @OneToMany(mappedBy = job)
    private List<JobStatusDate> statusDates;
}

@Entity
public class JobStatusDate {

    @Id
    @ManyToOne
    private Job job;

    @Id
    @ManyToOne
    private JobStatus status;

    private Date date;
}

@Entity
public class JobStatus {

    @Id
    private String status;

    // optional:
    @OneToMany(mappedBy = status)
    private List<JobStatusDate> statusDates;
}

或者,如果应用程序需要有效职务状态代码的内置知识(很可能,因为我预计它们与特定的业务逻辑相关联),那么您可以考虑删除JobStatus实体(但在数据库中保留表和FK关系)。那么JobStatusDate将具有普通的String状态码,而不是与JobStatus实体的关系。保留在DB中的FK关系将防止记录无效的状态代码,我猜这已经是它的预期目的了。

在这种情况下,您可以考虑更进一步,将状态码Map到适当的Java enum而不是String。最终结果可能如下所示:

public enum JobStatus {
    COMPLETED, ERROR, INSERTED, PROCESSING, VALIDATED, VALIDATING
}

@Entity
public class Job {
    @Id
    private Integer jobId;

    @OneToMany(mappedBy = job)
    @MapKey(name = status)
    private Map<JobStatus, JobStatusDate> statusDates;
}

@Entity
public class JobStatusDate {

    @Id
    @ManyToOne
    private Job job;

    @Id
    @Enumerated(EnumType.STRING)
    private JobStatus status;

    private Date date;
}

// No JobStatus entity

值得注意的是,这允许您MapJobJobStatusDate关系作为一个Map,这将是一个方便的许多类型的事情,我预计你可能想做的。

相关问题