![]() |
![]() |
Back to the Speedo user manual
Back to the Speedo documentation
The main condition of the inheritance support is about the namming of the persistent classes. Indeed according to the JDO specification the identifier has to be the same for all classes in an inheritance tree. Speedo supports application identifier but with a condition: the user must specify a filter permitting to know which persistent class is represented by an identifier instance. Let us take an example in order to explain better this condition.
With an filtered mapping of the inheritance, there is one table for all classes of the inheritance tree. You define the mapping of fields with the field declaration. By this way there is no duplicate declaration of the mapping (column name, table name, ...). You only have to specify the 'inheritance-mapping' extension in the subclasses, with the value 'filtered'.
With an horizontal mapping of the inheritance, there is one table
for each persistent and concret class of the inheritance tree. In each
persistent class, you define the mapping of the class and its fields.
There is a particular way to define the mapping of the inherited
fields.
abstract class Animal {
private boolean sex;
private String name;
private String species;
private Zoo zoo;
public Animal(String name, String species) {
this.name = name;
this.species = species;
}
public String getName() { return name; }
public String getSpecies() { return species; }
public boolean getSex() { return sex; }
public void setSex(boolean sex) { this.sex = sex; }
}
class Kangaroo extends Animal {
private int jumpLength;
public Kangaroo(String name) {
super(name, "kangaroo");
}
public int getJumpLength() { return jumpLength; }
public void setJumpLength(boolean jumpLength) { this.jumpLength = jumpLength; }
}
class Koala extends Animal {
private int lifeTime;
public Koala(String name) {
super(name, "koala");
}
public int getLifeTime() { return lifeTime; }
public void setLifeTime(boolean lifeTime) { this.lifeTime = lifeTime; }
}
class Zoo {
private String name;
private Collection animals
public Zoo(String name) {
this.name = name;
animals = new ArrayList();
}
public String getName() { return name; }
public Collection getAnimals() { return animals; }
}
<class name="Animal" identity-type="application" objectid-class="AnimalId"/>
<extension vendor-name="speedo" key="inheritance-filter" value="species"/>
...
</class>
<class name="Kangaroo" persistence-capable-superclass="Animal"/>
<extension vendor-name="speedo" key="inheritance-key" value="kangaroo"/>
...
</class>
<class name="Koala" persistence-capable-superclass="Animal"/>
<extension vendor-name="speedo" key="inheritance-key" value="koala"/>
...
</class>
The filtered mapping applied to the animal example is represented by the following diagrams:
![]() |
![]() |
The TAnimal table contains the instances of the Kangaroo and Koala classes. The following .jdo sections describe how to defined the filtered mapping:
<class name="Animal" identity-type="application" objectid-class="AnimalId"/>
<extension vendor-name="speedo" key="sql-name" value="TANIMAL"/>
<extension vendor-name="speedo" key="inheritance-filter" value="species"/>
<field name="name" primary-key="true">
<extension vendor-name="speedo" key="sql-name" value="NAME"/>
</field>
<field name="species" primary-key="true">
<extension vendor-name="speedo" key="sql-name" value="SPECIE"/>
</field>
...
</class>
<class name="Kangaroo" persistence-capable-superclass="Animal"/>
<extension vendor-name="speedo" key="inheritance-key" value="kangaroo"/>
<extension vendor-name="speedo" key="inheritance-mapping" value="filtered"/>
<field name="jumpLength">
<extension vendor-name="speedo" key="sql-name" value="JUMP"/>
</field>
...
</class>
<class name="Koala" persistence-capable-superclass="Animal"/>
<extension vendor-name="speedo" key="inheritance-key" value="koala"/>
<extension vendor-name="speedo" key="inheritance-mapping" value="filtered"/>
<field name="lifeTime">
<extension vendor-name="speedo" key="sql-name" value="LIFE"/>
</field>
...
</class>
You can note that the table name is defined in the root class even if the class is abstract. The mapping of the Animal fields are also defined in the section corresponding to the animal class. In the other hand the field mapping of Kangaroo or Koala classes are defined in their own class.
soon supported
abstract class Article {
private long id;
private String name;
private Catalog catalog;
public Article(long id) {
this.id = id;
}
public String getId() { return id; }
}
class Service extends Article {
private String f1;
public Service(long value) {
super(2 * value);
}
}
class Materiel extends Article {
private String f2;
public Materiel(long value) {
super(2 * value + 1);
}
}
class Catalog {
private String name;
private Collection articles
public Catalog(String name) {
this.name = name;
articles = new ArrayList();
}
}
<class name="Article" identity-type="application"/>
<extension vendor-name="speedo" key="inheritance-filter" value="(id % 2)"/>
...
</class>
<class name="Service" persistence-capable-superclass="Article"/>
<extension vendor-name="speedo" key="inheritance-key" value="0"/>
...
</class>
<class name="Materiel" persistence-capable-superclass="Article"/>
<extension vendor-name="speedo" key="inheritance-key" value="1"/>
...
</class>
The filtered mapping applied to the Article example is represented by the following diagrams:
![]() |
![]() |
The TArcticle table contains the instances of the Service and Materiel classes. The following .jdo sections describe how to define the filtered mapping:
<class name="Article" identity-type="application"/>
<extension vendor-name="speedo" key="sql-name" value="TARTICLE"/>
<extension vendor-name="speedo" key="inheritance-filter" value="(id % 2)"/>
<field name="id" primary-key="true">
<extension vendor-name="speedo" key="sql-name" value="LID"/>
</field>
<field name="name">
<extension vendor-name="speedo" key="sql-name" value="NAME"/>
</field>
<field name="catalog">
<extension vendor-name="speedo" key="target-foreign-keys" value="CATALOG"/>
</field>
</class>
<class name="Service" persistence-capable-superclass="Article"/>
<extension vendor-name="speedo" key="inheritance-key" value="0"/>
<extension vendor-name="speedo" key="inheritance-mapping" value="filtered"/>
<field name="f1">
<extension vendor-name="speedo" key="sql-name" value="F1"/>
</field>
</class>
<class name="Materiel" persistence-capable-superclass="Article"/>
<extension vendor-name="speedo" key="inheritance-key" value="1"/>
<extension vendor-name="speedo" key="inheritance-mapping" value="filtered"/>
<field name="f2">
<extension vendor-name="speedo" key="sql-name" value="F2"/>
</field>
</class>
You can note that the table name is defined in the root class even if the class is abstract. The mapping of the Article fields are also defined in the section corresponding to the Article class. On the other hand the field mappings of Service or Materiel classes are defined in their own class.
abstract class Form {
//the pk
private int id;
//the filter
private String title;
private ContactDetails contactDetails;
public Form(int id, String title, ContactDetails contactDetails) {
this.id = id;
this.title = title;
this.contactDetails = contactDetails;
}
public ContactDetails getContactDetails() {return contactDetails;}
public void setContactDetails(ContactDetails contactDetails) {this.contactDetails = contactDetails;}
public int getId() {return id;}
public void setId(int id) {this.id = id;}
public String getTitle() {return title;}
public void setTitle(String title) {this.title = title;}
}
class BookForm extends Form {
private int validTime;
public BookForm(int id, ContactDetails contactDetails, int validTime) {
super(id, "book", contactDetails);
this.validTime = validTime;
}
public int getValidTime() {return validTime;}
public void setValidTime(int validTime) {this.validTime = validTime;}
}
class PurchaseForm extends Form {
private int total;
private CreditCard creditCard;
public PurchaseForm(int id, ContactDetails contactDetails, int total, CreditCard creditCard) {
super(id, "purchase", contactDetails);
this.total = total;
this.creditCard = creditCard;
}
public int getTotal() {return total;}
public void setTotal(int total) {this.total = total;}
public CreditCard getCreditCard() {return creditCard;}
public void setCreditCard(CreditCard creditCard) {this.creditCard = creditCard;}
}
class name="Form" identity-type="application">
<extension vendor-name="speedo" key="inheritance-filter" value="title"/>
<field name="id" primary-key="true">
<extension vendor-name="speedo" key="sql-name" value="FORM_ID"/>
</field>
<field name="title"> <!-- title is not part of the primary key -->
<extension vendor-name="speedo" key="sql-name" value="FORM_TITLE"/>
</field>...
</class>
<class name="PurchaseForm" persistence-capable-superclass="Form">
<extension vendor-name="speedo" key="inheritance-key" value="purchase"/>
...
</class>
<class name="BookForm" persistence-capable-superclass="Form">
<extension vendor-name="speedo" key="inheritance-key" value="book"/>
...
</class>
The filtered mapping applied to the form example is represented by
the following diagram:
The FILTER_FORM table contains the instances of both BookForm and PurchaseForm classes. The following .jdo section describes how to define the filtered mapping:
<class name="Form" identity-type="application">
<extension vendor-name="speedo" key="sql-name" value="FILTER_FORM"/>
<extension vendor-name="speedo" key="inheritance-filter" value="title"/>
<field name="id" primary-key="true">
<extension vendor-name="speedo" key="sql-name" value="FORM_ID"/>
</field>
<field name="title">
<extension vendor-name="speedo" key="sql-name" value="FORM_TITLE"/>
</field>
...
</class>
<class name="BookForm" persistence-capable-superclass="Form">
<extension vendor-name="speedo" key="inheritance-mapping" value="filtered"/>
<extension vendor-name="speedo" key="inheritance-key" value="book"/>
<field name="validTime">
<extension vendor-name="speedo" key="sql-name" value="BOOK_VALID_TIME"/>
</field>
</class>
<class name="PurchaseForm" persistence-capable-superclass="Form">
<extension vendor-name="speedo" key="inheritance-mapping" value="filtered"/>
<extension vendor-name="speedo" key="inheritance-key" value="purchase"/>
<field name="total">
<extension vendor-name="speedo" key="sql-name" value="PURCHASE_TOTAL"/>
</field>
<field name="creditCard" persistence-modifier="persistent">
<extension vendor-name="speedo" key="target-foreign-keys" value="CARD_ID=PURCHASE_CARD_ID"/>
</field>
</class>
You can note that the table name is defined in the root class even if the class is abstract. The mapping of the shared fields is also defined in the section corresponding to the Form class. The mapping of specific fields for a subclass is defined in the subclass jdo section.