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

Fer*_*ndo 16 java hibernate jpa-2.0

我有以下实体:

@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;**
Run Code Online (Sandbox Code Playgroud)

我的属性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 {
       ...
}
Run Code Online (Sandbox Code Playgroud)

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

提前致谢,

rbe*_*nto 11

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

您只能映射直接注释的顶级类@Entity.这个顶级类可以实现一个接口.

长期以来一直在要求和讨论此功能.

另外看看这个这个.

根据您要完成的任务,可以选择具有每类策略的@Inheritance注释.

我希望它有所帮助.


ACV*_*ACV 8

有一个警告是可能的 - 您必须将 JPA 指向一个目标实体,该实体应该是一个具体的类。但是,它可以是实现您的接口的抽象类。因此,您必须打破良好设计的一项原则,特别是“优先考虑组合而不是继承”。

操作方法如下:

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

所以这里Task是一个接口,但是你必须声明一个抽象类BaseTask

  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;
    }
Run Code Online (Sandbox Code Playgroud)

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

  1. 您的具体课程:
@Entity
@DiscriminatorValue("api")
public class ApiTask extends BaseTask {
Run Code Online (Sandbox Code Playgroud)

或者

@Entity
@DiscriminatorValue("ssh")
public class SshTask extends BaseTask{
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,鉴别器值告诉 JPA 将加载什么任务(要实例化什么类)。


Vol*_*man 5

不,不能使用 JPA 或 Hibernate。

当使用允许属性作为接口的 Java 语言进行编码时,似乎很奇怪,像 JPA 这样的用于 Java 的持久性标准不支持作为接口的持久性属性。

当我的 ORM 强迫我重构我的“纯”OO 模型以便能够坚持它时,我总是发现它真的非常令人沮丧。

并不是说实现接口属性的持久化在技术上是不可能的——事实上,JDO 一直支持接口的持久化,这就是为什么我多年前开始在我自己的所有项目中使用它。

我一直想改用 JPA,不是因为它在技术上更胜一筹(事实上,恰恰相反),而只是因为“从众心态”。

在最近的合同工作中,我被迫获得了 JPA/Hibernate 的经验,在这样做的过程中,与 JDO/DataNucleus 相比,我已经体验到了这种组合的许多局限性和低效率。这是一次很棒的经历,因为它帮助我平息了加入“羊群”的愿望:)