Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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. 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. I've tried OpenJPA and (plain) Hibernate with no luck even though the latter's support for interfaces looked promising.

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-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. So far so good...

But what shall I do with the Tradeable interface? I would have to setup a separate hierarchy and map Stock in both hierarchies. 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. 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. I'd rather have the framework handle this automaticaly.

Ideally Hibernate would allow extending multiple interfaces, i.e. something like (note the extends attribute on the subclass element):

<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.

How about other frameworks? I've heard EclipseLink also has some support for interfaces but it's not well documented.

like image 961
kaiboy Avatar asked Apr 01 '12 21:04

kaiboy


People also ask

Can you inherit multiple interfaces in Java?

Java allows multiple inheritance using interfaces. Interfaces could only define abstract methods, that is, methods without any implementation. So if a class implemented multiple interfaces with the same method signature, it was not a problem. The implementing class eventually had just one method to implement.

CAN interfaces inherit from multiple interfaces?

An interface may inherit from multiple base interfaces, and a class or struct may implement multiple interfaces. Interfaces can contain methods, properties, events, and indexers. The interface itself does not provide implementations for the members that it declares.

What is multiple inheritance in Java using interface?

Multiple Inheritance is a feature of an object-oriented concept, where a class can inherit properties of more than one parent class. The problem occurs when there exist methods with the same signature in both the superclasses and subclass.

Can interface inherit another interface Java?

A Java interface can inherit multiple other interfaces. A Java class can implement multiple interfaces (and inherit from one class).


1 Answers

I don't think you will find any ORM able to handle interfaces hierarchy nicely. So I won't talk about ORMs here but I'm going to show you how to implement your example using 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. See http://qi4j.org

In Qi4j, domain state is modeled using Entities and Values. 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).

Note that Qi4j EntityStores are not only SQL based but support NoSQL databases too. See the available extensions here: http://qi4j.org/latest/extensions.html

See the Qi4j documentation if you have more questions.

like image 109
eskatos Avatar answered Oct 07 '22 00:10

eskatos