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也对接口有一些支持,但它没有很好的文档记录.
我认为您不会发现任何 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 文档。