Java ORM : Multiple (interface) inheritance

标签 java orm interface multiple-inheritance

我想使用 Java 的 ORM 框架之一将域模型映射到关系数据库。不幸的是,它们似乎都没有充分支持实现多个接口(interface)的类。假设我想映射如下内容:

public interface Quotable {
}

public interface Tradable {
}

// StockIndex only implements Quotable as it cannot be trade directly
public class StockIndex implements Quotable {
}

// Stock implements both interfaces as there are market quotes and can be traded
public class Stock implements Quotable, Tradable {
}

public class Quote {
    private Quotable quotable;
}

public class Trade {
    private Tradable tradable;
}

所以我想要实现的是,报价可以引用任何报价表(股票、股票指数等),而交易只能引用可交易实体。我已经尝试过 OpenJPA 和(普通的)Hibernate,但没有成功,尽管后者对接口(interface)的支持看起来很有前途。

是否有任何框架可以处理我的场景?或者有什么好的理由不应该将其映射到数据库吗?如果是这样,我的模型应该如何修改?

我最初的 Hibernate 映射看起来像这样(我没有展示任何 OpenJPA 的东西,因为它不支持接口(interface)继承,或者至少我不知道如何实现):

<hibernate-mapping package="com.foo">
    <class name="Quotable" table="quotable" >
        <id type="java.lang.Long" column="id">
            <generator class="sequence" />
        </id>

        <discriminator column="type" type="string" />

        <subclass name="StockIndex">
            <join table="stock_index" >
                <key column="id"/>
                <property name="name" column="name" access="field" />
            </join>
        </subclass>

        <subclass name="Stock">
            <join table="stock" >
                <key column="id"/>
                <property name="name" column="name" access="field" />
            </join>
        </subclass>
    </class>
</hibernate-mapping>

这与 Hibernate documentation 中的示例几乎相同并生成一个带有 id 和字符串鉴别器列的 quotable 表,一个带有 id 和索引名称的 stock_index 表,以及一个 stock 表> 带有 ID 和股票名称。到目前为止一切顺利...

但是我应该如何处理 Tradeable 界面?我将不得不设置一个单独的层次结构并在两个层次结构中映射 Stock。我确实尝试过这个但是必须为 Stock 定义不同的实体名称(并且需要包括 this patch )但是由于外键违规这也不起作用。我尝试了其他一些不起眼的东西,但也没有用。

无论如何,两次映射 Stock 并不是一个好的解决方案,因为应用程序必须记住两次添加 Stock 实例 - 每个接口(interface)一次。我宁愿让框架自动处理这个问题。

理想情况下,Hibernate 将允许扩展多个接口(interface),例如(注意 subclass 元素上的 extends 属性):

<subclass name="Stock" extends="Quotable, Tradable" >
    <join table="stock" >
        <key column="id"/>
        <property name="name" column="name" access="field" />
    </join>
</subclass>

关于如何映射我的示例的任何其他想法?我现在了解了 <any> 看起来对我有用的元素,但我还没有理解它的所有含义。

其他框架呢?我听说 EclipseLink 也有一些接口(interface)支持,但没有很好的文档记录。

最佳答案

我认为您找不到任何能够很好地处理接口(interface)层次结构的 ORM。 所以我不会在这里谈论 ORM,但我将向您展示如何使用 Qi4j 实现您的示例。

Qi4j 是面向复合编程的实现,使用标准 Java 平台和以领域为中心的应用程序开发框架,包括从 AOP、DI 和 DDD 演变而来的概念。参见 http://qi4j.org

在 Qi4j 中,域状态是使用实体和值建模的。在以下代码示例中,我假设一切都是实体,但您的情况可能会有所不同。

由于实体仅使用接口(interface)声明,因此您的用例应该很适合。

interface Quotable { ... }
interface Tradable { ... }
interface StockIndex extends Quotable { ... }
interface Stock extends Quotable, Tradable { ... }
interface Quote {
    Association<Quotable> quotable();
}
interface Trade {
    Association<Tradable> tradable();
}

然后您可以将这些存储在 EntityStore 中,并使用查询 API 轻松检索它们(并以完全多态的方式)。

请注意,Qi4j EntityStores 不仅基于 SQL,还支持 NoSQL 数据库。在此处查看可用的扩展:http://qi4j.org/latest/extensions.html

如果您有更多问题,请参阅 Qi4j 文档。

关于Java ORM : Multiple (interface) inheritance,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9968494/

相关文章:

java - 从 XML 文件中删除 header 的简单方法

java - HIbernate:分离父级和所有子级

c# - 使协变接口(interface)向后兼容

java - 未报告 IOException 错误,但有 "throws Exception"并且 Try 和 Catch 位于方法内

java - HSQL 数据库中的连接方式

java - JPA Hibernate 两个外键指向同一个表

hibernate 映射异常 : Repeated column in mapping for entity

performance - EJB3 - Session Bean调用另一个bean接口(interface)的方法

java - 将用户创建的类标记为 "plugins"

java - Eclipse 中的错误? org.eclipse.jdt.internal.compiler.lookup.ArrayBinding 无法转换为 org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding