Java ORM:多个(接口)继承

kai*_*boy 7 java orm interface multiple-inheritance

我想使用一个Java的ORM框架将域模型映射到关系数据库.不幸的是,它们似乎都没有足够的支持实现多个接口的类.说我想要映射如下:

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

因此,我想要实现的是,报价可以引用任何报价(股票,股票指数和其他),而交易只能引用可交易实体.我已经尝试过OpenJPA和(普通)Hibernate没有运气,尽管后者对界面的支持看起来很有希望.

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

我最初的Hibernate映射看起来像这样(我没有显示任何OpenJPA的东西,因为它不支持接口继承或至少我无法弄清楚如何):

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

这是几乎等同于在例如Hibernate文档和结果表中的可引用的一个id和一个字符串鉴别列,表stock_index带有ID和索引的名字和一张桌子股票与ID和股票的名称.到现在为止还挺好...

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

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

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

<subclass name="Stock" extends="Quotable, Tradable" >
    <join table="stock" >
        <key column="id"/>
        <property name="name" column="name" access="field" />
    </join>
</subclass>
Run Code Online (Sandbox Code Playgroud)

我的例子如何映射的任何其他想法?我现在已经了解了<any>看起来可能对我有用的元素,但我还没有理解它的所有含义.

其他框架怎么样?我听说EclipseLink也对接口有一些支持,但它没有很好的文档记录.

esk*_*tos 3

我认为您不会发现任何 ORM 能够很好地处理接口层次结构。因此,我不会在这里讨论 ORM,但我将向您展示如何使用 Qi4j 实现示例。

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

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

由于实体仅使用接口来声明,因此您的用例应该很好地适合。

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

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

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

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