Skip to content
btoddb edited this page Jan 20, 2011 · 6 revisions

Inheritance in Hector Object Mapper (HOM) is JPA style inheritance. Where JPA has several ways to implement inheritance, HOM only works with “single table” – meaning all derivations of the base class are stored in a single ColumnFamily row. At this time I feel this is sufficient because there is no rigid schema defined in Cassandra. Each object only stores in a Cassandra “row” what it needs. In traditional RDBMS there is a good argument for having multiple inheritance strategies because of wasting space or rows becoming too large to accommodate all possible derivations.

So let’s start with an example modeling furniture. We have a chair, a table, and a couch – each a type of furniture. So we’ll create three objects; Chair, Table, and Couch, each derived from a base class, Furniture:

  @Entity
  @Table("Furniture")
  @Inheritance
  @DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.STRING)
  @DiscriminatorValue("") // means catch all derivatives that don't specify a 'type'
  public class Furniture {
      @Id
      private int id;
  
      @Column("material")
      private String material;
  
      @Column("color")
      private String color;

      public String getMaterial() {
          return material;
      }

      //  getters/setters required, but not showing to conserve space
  
  }


  @Entity
  @DiscriminatorValue("chair")
  public class Chair extends Furniture {
      @Column("recliner")
      private boolean recliner;
  
      @Column("arms")
      private boolean arms;

      //  getters/setters required, but not showing to conserve space
  
  }


  @Entity
  @DiscriminatorValue("table")
  public class Table extends Furniture {
      @Column("extendable")
      private boolean extendable;
  
      @Column("shape")
      private String shape;

      //  getters/setters required, but not showing to conserve space
  
  }


  @Entity
  @DiscriminatorValue("couch")
  public class Couch extends Furniture {
      @Column("foldOutBed")
      private boolean foldOutBed;
  
      @Column("numCushions")
      private int numCushions;

      //  getters/setters required, but not showing to conserve space

  }


  @Entity
  @DiscriminatorValue("table_desk")
  public class Desk extends Table {

      @Column("numDrawers")
      private int numDrawers;

      //  getters/setters required, but not showing to conserve space

  }

With single table inheritance all derivations of the class hierarchy are stored in the same ColumnFamily. The base class defines the ColumnFamily using @Table, and it is illegal to define @Table in any of its derived classes. There can be multiple levels of inheritance as long as each is annotated with @Entity and each defines a unique DiscriminatorValue (See class, Desk, above.)

The new annotations to discuss are:

  • @Inheritance : defines base class of inheritance hierarchy
  • @DiscriminatorColumn : the column name to use for discriminating between class types
  • @DiscriminatorValue : a unique value for each class in the hierarchy

@Inheritance is required by the base class of the hierarchy and signals the mapper to store the set of classes in the hierarchy based on the strategy. @Inheritance can specify an inheritance “strategy”, but at this moment, on JPA style “single table” storage is available.

@DiscriminatorColumn is required by the base class of the hierarchy and defines the column name for storing a discriminator value. A type can also be specified (see Furniture class) for the column value. The acceptable values are defined by the enumeration, DiscriminatorType. (STRING is the default.)

@DiscriminatorValue is required by all classes in the hierarchy and defines the class’ unique value within the hierarchy. This value is stored in the DiscriminatorColumn when the object is saved. It is used to determine the class type when loading data from Cassandra.

##Saving
Saving is no different than non-inheritance. Use an EntityManager to save the object and as long as the classes are properly configured, everything will simply work!

  Keyspace keyspace = HFactory.createKeyspace("TestKeyspace", cluster);
  entityMgr = new EntityManager(keyspace, "com.mycompany.furniture");
  Desk desk = new Desk();
  desk.setId( 4 );
  desk.setMaterial("pressBoard");
  desk.setColor("black");
  desk.setExtendable(false);
  desk.setShape("rectangle");
  desk.setNumDrawers(2);
  entityMgr.save(desk);

The above code sample will save to the ColumnFamily Furniture, key = 4, the following properties: material, color, extendable, shape, numDrawers, and type. The discriminator column, type, will have a value of “table_desk”.

##Loading
To load the Desk object saved above is also simple. The following code will use the EntityManager to load a piece of furniture:

  Keyspace keyspace = HFactory.createKeyspace("TestKeyspace", cluster);
  entityMgr = new EntityManager(keyspace, "com.mycompany.furniture");
  Furniture furniturePiece = entityMgr.load(Furniture.class, 4);
  System.out.println( "class type = " + furniturePiece.getClass().getName());
Clone this wiki locally