Я бы хотел отобразить модель предметной области в реляционную базу данных, используя одну из сред ORM для Java. К сожалению, ни один из них не имеет адекватной поддержки классов, реализующих несколько интерфейсов. Скажем, я хочу отобразить что-то вроде:
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;
}
Итак, я пытаюсь добиться того, чтобы Цитата могла ссылаться на любой Котировочный материал (Stock, StockIndex и другие), тогда как Сделка может ссылаться только на Торгуемые сущности. Я попробовал 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>
Это в значительной степени идентично примеру в документации Hibernate и приводит к таблице quotable с идентификатором и столбцу распознавателя строк, таблице stock_index с идентификатором и индексом 'имя и таблица акция с идентификатором и названием акции. Пока все хорошо ...
Но что мне делать с интерфейсом 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>
Любые другие идеи, как мой пример может быть отображен? Теперь я узнал об элементе <any>
, который выглядит так, как будто он может работать на меня, но я еще не понял всех его последствий.
Как насчет других фреймворков? Я слышал, что EclipseLink также имеет некоторую поддержку интерфейсов, но она недостаточно хорошо документирована.