1

这是我找不到解决方案的问题,我想,这要么是不可能的,要么我的整个想法走错了方向。

最初我的 JPA 层次结构的一部分是这样的:

@MappedSuperclass
public abstract class AbstractEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    protected Long id;
    ..... 
}

@Audited
@Entity
@Table(name = "T_MEETING")
public class Meeting extends AbstractEntity implements Groupable {...}

@Audited
@Entity
@Table(name = "T_QUESTION")
public class Question extends AbstractEntity implements Groupable {...}

该数据库已经使用了一段时间,直到出现某些对象中需要自定义字段为止。

我决定遵循以下路线 - 将抽象实体作为具有自定义字段的对象的基础:

@Audited
@Entity
@Table(name = "T_CF_OBJECT")
@Inheritance(strategy = InheritanceType.JOINED)
@PrimaryKeyJoinColumn(name = "ID", referencedColumnName = "CF_OBJECT_ID")
public abstract class EntityWithCustomFields extends AbstractEntity {...}

@Audited
@Entity
@Table(name = "T_QUESTION")
public class Question extends EntityWithCustomFields implements Groupable {...}

@Audited
@Entity
@Table(name = "T_MEETING")
public class Meeting extends EntityWithCustomFields implements Groupable {...}

我尝试了不同的选择,但总是有一个问题:

  1. 我猜,JPA 提供程序(在我的情况下是休眠)首先插入父级,因此它CF_OBJECT_IDnull

    Hibernate:插入 t_cf_object (id, cf_object_id) 值 (null, ?) Hibernate: 插入 t_meeting (active, date, c_group, last_notification_date, only_for_members, place, questions_order, subject, update_date, id) 值 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)

  2. 如果我在基本实体上省略@PrimaryKeyJoinColumn注释,则其后代的 sIdIds 用作连接列,它导致子类表没有相同的 id。一开始这很好,但是我们已经在两个表中拥有大量记录,并且它们在id列中具有相同的值。更改表中的 s 不是一种选择id

在我的情况下使用继承的正确方法是什么,所以它尽可能无缝地进入?很高兴了解如何首先使休眠持久子类实例,然后将其 id 传递给持久化的超类。必须有注释,对吧?

编辑:至于使用建议@MappedSuperclass

@MappedSuperClass由于以下原因,我真的不能使用 a 。父类EntityWithCustomFields用于通过类的ManyToOne关系来引用CustomFieldValue。在代码中,它如下所示:

@Entity
@Audited
@Table(name = "T_CF_VALUES")
public class CustomFieldValue extends AbstractEntity {
    @ManyToOne
    @JoinColumn(name = "customFieldObject", nullable = false)
    private EntityWithCustomFields customFieldObject;
    ....
}
@Audited
@Entity
@Table(name = "T_CF_OBJECT")
@Inheritance(strategy = InheritanceType.JOINED)
@PrimaryKeyJoinColumn(name = "ID", referencedColumnName = "CF_OBJECT_ID")
public abstract class EntityWithCustomFields extends AbstractEntity {
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "customFieldObject", cascade = CascadeType.ALL)
    private List<CustomFieldValue> customFields;
    ....
 }

我不认为@MappedSuperclass可以用于这种东西。

4

1 回答 1

0

在我看来,您不希望这里的实体继承,而是为您的具有自定义字段的实体提供一个额外的映射超类。

当您具有真正的 is-a 函数关系时,必须使用实体继承。例如,一张发票可能有一个产品列表,而产品实体将是继承树(蔬菜、肉类、服装等)的根。在这种情况下,蔬菜是一种产品,当然两个产品可能没有相同的 ID,因为例如价格实体可以通过外键引用产品,如果两个产品具有相同的 ID,它就不会根本不工作。

在您的情况下,具有自定义字段的实体完全不相关。它们只是碰巧有公共字段,您想通过将这些公共字段放在超类中来考虑这一点。这就是 MappSuperclass 的用途。并且这些自定义字段应该在每个实体表中重复。无论如何,这将比联合继承更有效(这会导致更多的查询,以及更复杂和更难优化的查询)。

于 2012-05-16T05:56:57.660 回答