Chciałbym zmapować model domeny do relacyjnej bazy danych za pomocą jednego z frameworków ORM dla Javy. Niestety, żaden z nich nie wydaje się mieć adekwatnego wsparcia dla klas implementujących wiele interfejsów. Chcę powiedzieć map coś takiego:Java ORM: Wielokrotne dziedziczenie (interfejs)
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;
}
Więc co staram się osiągnąć to, że żądanie może odwoływać żadnych quotable (Stock, StockIndex i inne), podczas gdy Transakcja może odwoływać się wyłącznie podmioty zbywalnych. Próbowałem OpenJPA i (zwykły) Hibernate bez powodzenia, mimo że obsługa tych interfejsów wyglądała obiecująco.
Czy istnieją jakieś ramy, które mogą obsłużyć mój scenariusz? Czy istnieją jakieś dobre powody, dla których nie powinno się mapować do bazy danych? Jeśli tak, to w jaki sposób zmodyfikować mój model?
Moja początkowa mapowania Hibernate wyglądał mniej więcej tak (ja nie pokazując żadnych OpenJPA rzeczy, ponieważ nie obsługuje dziedziczenie interfejsu lub przynajmniej nie mogłem dowiedzieć się, w jaki sposób):
<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>
To jest prawie identyczny przykład w Hibernate documentation i wyniki w tabeli quotable z id i kolumny ciąg dyskryminatora, stół stock_index z identyfikatorem oraz indeksu”nazwy i stół magazynie z identyfikatorem a nazwa akcji. Do tej pory tak dobrze ...
Co jednak powinienem zrobić z interfejsem Tradeable? Musiałbym ustawić oddzielną hierarchię i zapasy map w obu hierarchiach. Próbowałem tego, ale musiałem zdefiniować różne nazwy jednostek dla Stock (i musiałem dodać this patch), ale to też nie zadziałało z powodu naruszenia klucza obcego. Wypróbowałem kilka innych niejasnych rzeczy, które też nie działały.
W każdym razie dwukrotne odwzorowanie zapasów nie byłoby dobrym rozwiązaniem, ponieważ aplikacja musiałaby pamiętać, dodając instancje magazynowe dwukrotnie - raz dla każdego interfejsu. Wolałbym, aby framework obsługiwał to automatycznie.
Idealnie hibernacji pozwoli rozszerzenie wiele interfejsów, czyli coś jak (należy zwrócić uwagę na rozciąga atrybut na podklasy elementu):
<subclass name="Stock" extends="Quotable, Tradable" >
<join table="stock" >
<key column="id"/>
<property name="name" column="name" access="field" />
</join>
</subclass>
jakieś inne pomysły jak mój przykład można odwzorować? Dowiedziałem się już o elemencie <any>
, który wygląda na to, że może działać dla mnie, ale muszę jeszcze zrozumieć wszystkie jego implikacje.
Co powiesz na inne frameworki? Słyszałem, że EclipseLink ma również wsparcie dla interfejsów, ale nie jest dobrze udokumentowany.
Tak naprawdę nie wyjaśniłeś, co nie działa lub jak wykonujesz mapowanie. –
Mam teraz dołączone moje mapowanie Hibernacji z bardziej szczegółowymi informacjami o tym, co wypróbowałem. Mam nadzieję, że teraz staje się bardziej przejrzysta. – kaiboy