27

我有以下实体:

@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?

提前致谢,

4

4 回答 4

12

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

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

此功能已被请求并讨论了很长时间。

也看看thisthis

根据您要完成的工作,使用每类表策略的@Inheritance注释可能是一种选择。

我希望它有所帮助。

于 2012-09-27T20:32:23.757 回答
5

不,JPA 或 Hibernate 不可能。

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

当我的 ORM 强迫我重构我的“纯”OO 模型以便能够坚持下去时,我总是觉得非常令人沮丧。

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

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

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

于 2018-02-18T14:54:39.557 回答
4

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

这是如何做到的:

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

所以这里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;
    }

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

  1. Your concrete classes:
@Entity
@DiscriminatorValue("api")
public class ApiTask extends BaseTask {

or

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

As you can see the discriminator value tells JPA what task it is going to load (what class to instantiate).

于 2020-04-18T21:48:17.033 回答
0

您需要使用您喜欢的任何策略(请参阅文档)在 JPA 中正确设置 ScriptItem 的继承,然后 JPA 会很聪明。

于 2012-09-27T18:18:25.503 回答