JPA - 我可以使用@DiscriminatorValue创建一个没有自己的表的Entity类吗?

时间:2010-04-26 11:29:25

标签: java inheritance jpa

这可能有点复杂,所以我会尽力描述我的情况 - 这也是我在这里的第一篇文章,所以请原谅格式错误等等!

我正在使用JPA加入继承和数据库结构,如下所示:

ACTION
---------
ACTION_ID
ACTION_MAPPING_ID
ACTION_TYPE

DELIVERY_CHANNEL_ACTION
--------------------------
ACTION_ID
CHANNEL_ID

OVERRIDE_ADDRESS_ACTION
--------------------------
ACTION_ID
(various fields specific to this action type)

所以,用简单的英语,我有多种不同类型的动作,都共享一个ACTION_MAPPING,它从'父'ACTION表中引用。 DELIVERY_CHANNEL_ACTION和OVERRIDE_ADDRESS_ACTION都有自己的额外补充数据,并用FK映射到ACTION。

现实世界中,我也有一个'抑制'动作,但是它没有自己的任何补充数据,所以它没有相应的表 - 它只需要一个ACTION_MAPPING,它存储在行动表。

希望你到目前为止和我在一起......

我正在从零开始创建一个新项目,所以我能做的很灵活,但显然希望从一开始就做到这一点!

我当前的实现有三个实体,其定义如下:

@Entity
@Table(name="ACTION")
@Inheritance(strategy=InheritanceType.JOINED)
@DiscriminatorValue("SUPPRESS")
public class Action

@Entity
@Table(name="DELIVERY_CHANNEL_ACTION")
@DiscriminatorValue("DELIVERY_CHANNEL")
public class DeliveryChannelAction extends Action

@Entity
@Table(name="OVERRIDE_ADDRESS_ACTION")
@DiscriminatorValue("OVERRIDE_ADDRESS")
public class OverrideAddressAction extends Action

那就是 - 我有一个具体的基类,Action,带有Joined继承策略。 DeliveryChannelAction和OverrideAddressAction都扩展了Action。

这里有什么问题,我的Action类是这两个动作的基类,但也构成了抑制动作的具体实现。

目前这种情况有效,但在某些时候可能会增加更多的行动,并且他们中的一些人有可能会像SUPPRESS一样没有补充数据,这将开始变得困难!

所以...我想在对象模型世界中做的是让Action变为抽象,并创建一个SuppressAction类,除了拥有@DiscriminatorValue(“SUPPRESS”)之外它是空的。

我尝试过完全按照上面描述的内容进行操作,因此,将操作更改为:

@Entity
@Table(name="ACTION")
@Inheritance(strategy=InheritanceType.JOINED)
public abstract class Action

并创建:

@DiscriminatorValue("SUPPRESS")
public class SuppressAction extends Action

但没有运气 - 它似乎适用于DeliveryChannelAction和OverrideAddressAction,但是当我尝试创建一个SuppressAction并坚持它时,我得到:

java.lang.IllegalArgumentException: Object: com.mypackage.SuppressAction[actionId=null] is not a known entity type.
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.registerNewObjectForPersist(UnitOfWorkImpl.java:4147)
    at org.eclipse.persistence.internal.jpa.EntityManagerImpl.persist(EntityManagerImpl.java:368)
    at com.mypackage.test.util.EntityTestUtil.createSuppressAction(EntityTestUtil.java:672)
    at com.mypackage.entities.ActionTest.testCRUDAction(ActionTest.java:27)

我认为这是因为SuppressAction没有注册为实体,但我不知道如何做到这一点,因为它没有关联的表。

任何指针,无论是完整的答案还是谷歌的提示(我的想法都没有!),非常欢迎:)

编辑:纠正我的堆栈跟踪。

2 个答案:

答案 0 :(得分:1)

您可以InheritanceType.SINGLE_TABLE

有多种方法可以为不同的分支提供多种继承类型。 See this question

答案 1 :(得分:1)

我认为我找到了一个适用于我的解决方案,我的实体现在看起来像:

@Entity
@Table(name="ACTION")
@Inheritance(strategy=InheritanceType.JOINED)
@DiscriminatorValue("SUPPRESS")
public abstract class Action

@Entity
@Table(name="DELIVERY_CHANNEL_ACTION")
@DiscriminatorValue("DELIVERY_CHANNEL")
public class DeliveryChannelAction extends Action

@Entity
@Table(name="OVERRIDE_ADDRESS_ACTION")
@DiscriminatorValue("OVERRIDE_ADDRESS")
public class OverrideAddressAction extends Action

@Entity
@Table(name="ACTION")
@DiscriminatorValue("SUPPRESS")
public class SuppressAction extends Action

所以,基本上我所缺少的只是在我的SuppressAction类中引用'parent'表,我愚蠢地假设它不起作用。我的所有测试都是通过这个,它似乎正在工作;如果我将来需要添加其他动作,似乎会很高兴,使用不同的@DiscriminatorValue的SuppressAction副本按预期工作,所以我觉得我很高兴。