具有接口属性的 JPA 实体,可能吗?

2022-09-01 13:19:41

我有以下实体:

@Entity
public class TestCaseStep implements JPAEntity<Integer> {

        ...

    @Column(name="STEP_NUMBER")
    private Integer stepNumber;

    @Enumerated(EnumType.STRING)
    @Column(name="ACTION")
    private Action action;

    **@ManyToOne
    @JoinColumn(name="connector")
    private ScriptItem connector;**

我的属性 ScriptItem 是其他 3 个类的接口。是否可以配置 JPA 以在运行时执行中设置正确的类 ID?

其他资源:

public interface ScriptItem {

    String getValue();
    ScriptItemType getType();
}

@Entity
@Table(name="DAT_FEED_XML")
public class FeedXml implements JPAEntity<Integer>, ScriptItem {
    ...
}

@Entity
@Table(name="DAT_DB_STMT")
public class DbStatement implements JPAEntity<Integer>, ScriptItem {
       ...
}

我应该使用哪些注释来让 JPA 理解我想要保存 3 个类之一的 ID?

提前致谢,


答案 1

这确实是一个好主意,但不幸的是,JPA不支持将接口直接映射为实体属性。

您只能映射直接使用 注释的顶级类。不过,这个顶级类可以实现一个接口。@Entity

此功能已被请求和讨论很长时间

也看看这个这个

根据您要完成的任务,@Inheritance具有按类表策略的注释可能是一种选择。

我希望它有帮助。


答案 2

有一个警告是可能的 - 你必须将JPA指向一个目标实体,它应该是一个具体的类。但是,它可以是实现接口的抽象类。因此,你必须打破好设计的一个原则,特别是 - “更喜欢构图而不是继承”。

操作方法如下:

  1. 在您的用户类(引用您的接口)中:Task
    @OneToOne(targetEntity = BaseTask.class)
    private Task task;

所以这里有一个接口,但你必须声明一个抽象类。TaskBaseTask

  1. 在您的 :BaseTask
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="task_type")
@Table(name="Task")
public abstract class BaseTask implements Task{

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    }

这里重要的是 - 因为继承树的所有字段都将存储在1个表中(您使用上面的注释指定了这一点。因此,此鉴别器列将包含一个标签,该标签将允许JPA区分您正在谈论的任务类型@DiscriminatorColumn@Inheritance(strategy = InheritanceType.SINGLE_TABLE)

  1. 您的具体类:
@Entity
@DiscriminatorValue("api")
public class ApiTask extends BaseTask {

@Entity
@DiscriminatorValue("ssh")
public class SshTask extends BaseTask{

如您所见,鉴别器值告诉 JPA 它将加载什么任务(要实例化哪个类)。


推荐