简体   繁体   English

Java ORM:多个(接口)继承

[英]Java ORM: Multiple (interface) inheritance

I'd like to map a domain model to a relational database using one of the ORM frameworks for Java. 我想使用一个Java的ORM框架将域模型映射到关系数据库。 Unfortunately, none of them seem to have adequate support for classes implementing multiple interfaces. 不幸的是,它们似乎都没有足够的支持实现多个接口的类。 Say I want to map something like: 说我想要映射如下:

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;
}

So what I'm trying to achieve is that a Quote can reference any Quotable (Stock, StockIndex and others) while a Trade can only reference Tradable entities. 所以我想要实现的是Quote可以引用任何Quotable(股票,StockIndex和其他),而Trade只能引用Tradable实体。 I've tried OpenJPA and (plain) Hibernate with no luck even though the latter's support for interfaces looked promising. 我已经尝试过OpenJPA和(普通)Hibernate没有运气,尽管后者对界面的支持看起来很有希望。

Is there any framework that can handle my scenario? 有没有可以处理我的场景的框架? Or are there any good reasons why this shouldn't be mapped to a database? 或者有什么理由不应该映射到数据库吗? If so, how should my model be modified? 如果是这样,我的模型应该如何修改?

My initial Hibernate mapping looked something like this (I'm not showing any OpenJPA stuff as it doesn't support interface inheritance or at least I couldn't figure out how): 我最初的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>

This is pretty much identical to the example in the Hibernate documentation and results in a table quotable with an id and a string discriminator column, a table stock_index with an id and the index' name and a table stock with an id and the stock's name. 这是几乎等同于在例如Hibernate文档和结果在新书用一个ID和一个字符串鉴别列,一个ID和索引的名字和一张桌子股票与ID和股票的名称的表stock_index的表。 So far so good... 到现在为止还挺好...

But what shall I do with the Tradeable interface? 但是我应该如何处理Tradeable界面? I would have to setup a separate hierarchy and map Stock in both hierarchies. 我必须在两个层次结构中设置单独的层次结构并映射Stock。 I did try this but had to define different entity names for Stock (and needed to include this patch ) but this also didn't work due to foreign key violations. 我确实试过这个但是必须为Stock定义不同的实体名称(并且需要包含这个补丁 ),但由于外键违规,这也没有用。 I tried a couple of other obscure things that didn't work either. 我尝试了其他一些不起作用的模糊不清的东西。

Anyway, mapping Stock twice wouldn't be a good solution as the application would have to remember adding Stock instances twice - once for each interface. 无论如何,两次映射股票不是一个好的解决方案,因为应用程序必须记住两次添加Stock实例 - 每个接口一次。 I'd rather have the framework handle this automaticaly. 我宁愿让框架自动处理。

Ideally Hibernate would allow extending multiple interfaces, ie something like (note the extends attribute on the subclass element): 理想情况下,Hibernate允许扩展多个接口,例如(注意子类元素上的extends属性):

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

Any other ideas how my example can be mapped? 我的例子如何映射的任何其他想法? I've now learned about the <any> element which looks like it might work for me but I have yet to understand all its implications. 我现在已经了解了<any>元素,看起来它可能对我有用,但我还没有理解它的所有含义。

How about other frameworks? 其他框架怎么样? I've heard EclipseLink also has some support for interfaces but it's not well documented. 我听说EclipseLink也对接口有一些支持,但它没有很好的文档记录。

I don't think you will find any ORM able to handle interfaces hierarchy nicely. 我认为你不会发现任何能够很好地处理接口层次结构的ORM。 So I won't talk about ORMs here but I'm going to show you how to implement your example using Qi4j. 所以我不会在这里讨论ORM,但我将向您展示如何使用Qi4j实现您的示例。

Qi4j is an implementation of Composite Oriented Programming, using the standard Java platform and a framework for domain centric application development, including evolved concepts from AOP, DI and DDD. Qi4j是面向复合的编程实现,使用标准Java平台和面向域中心的应用程序开发框架,包括来自AOP,DI和DDD的演化概念。 See http://qi4j.org http://qi4j.org

In Qi4j, domain state is modeled using Entities and Values. 在Qi4j中,域状态使用实体和值建模。 In the following code sample I assume that everything is an Entity but your mileage may vary. 在下面的代码示例中,我假设一切都是实体,但您的里程可能会有所不同。

As Entities are declared using only interfaces, your use case should fit in nicely. 由于实体仅使用接口声明,因此您的用例应该很好地适应。

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

You can then store theses in an EntityStore and use the Query API to retrieve them easily (and in a fully polymorphic way). 然后,您可以将这些存储在EntityStore中,并使用查询API轻松地检索它们(并以完全多态的方式)。

Note that Qi4j EntityStores are not only SQL based but support NoSQL databases too. 请注意,Qi4j EntityStores不仅基于SQL,还支持NoSQL数据库。 See the available extensions here: http://qi4j.org/latest/extensions.html 请在此处查看可用的扩展程序: http//qi4j.org/latest/extensions.html

See the Qi4j documentation if you have more questions. 如果您有更多问题,请参阅Qi4j文档。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM