Ibatis Tutorial: Inheritance Strategies

The first advanced feature of Ibatis I want to introduce is inheritance strategies. Several concepts and features will be introduced along the way. This tutorial assumes the knowledge and code from my Spring and Ibatis Tutorial.

Imagine we wanted to select all the parties in our database.


package com.cforcoding;

public class Party {
    private Long id;
    private String type;
    private String name;

    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    public String getType() { return type; }
    public void setType(String type) { this.type = type; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }


<select id="selectAllParties" resultClass="com.cforcoding.Party">
  SELECT id, party_type type, name
  FROM party


    @Transactional(propagation = Propagation.SUPPORTS)
    public List<Party> selectAllParties() {
        return getSqlMapClientTemplate().queryForList("selectAllParties");

The obvious interface is omitted and will be simply assumed in future. The one addition to this code that's worth noting is the addition of the @Transactional annotation declaring this method supports transactions. Why? It's a select so doesn't require a transaction but if it were to run within a transaction, you would probably want it to select data not yet committed by that transaction.

This code uses the queryForList() API call. This simply returns all the rows in a List. I've given that list a generic type, which is the reason for @SuppressWarnings("unchecked"). Java can't know the type of objects returned.

This simple code works fine but can be improved. The first thing to note is that Party has a type code of P or C, stored as a string. This is an obvious candidate for being an enumeration.


package com.cforcoding;

public enum PartyType {
    PERSON("P", "Person"),
    COMPANY("C", "Company");
    private final String code;
    private final String desc;

    PartyType(String code, String desc) {
        this.code = code;
        this.desc = desc;

    public String getCode() {
        return code;
    public String getDescription() {
        return desc;
    public static PartyType find(String code) {
        for (PartyType type : values()) {
            if (type.code.equals(code)) {
                return type;
        return null;

This is a basic enum with a couple of features added. Firstly, it has state, being the code and a short description of what that code means. Secondly, there is a finder method to map a code as text to a particular instance.

Ibatis supports the mapping of custom types to and from the database through type handlers.


A type handler can implement either TypeHandlerCallback or TypeHandler. I generally favour the former for having a simpler interface.

package com.cforcoding;

import com.ibatis.sqlmap.client.extensions.TypeHandlerCallback;
import com.ibatis.sqlmap.client.extensions.ParameterSetter;
import com.ibatis.sqlmap.client.extensions.ResultGetter;

import java.sql.SQLException;

public class PartyTypeHandler implements TypeHandlerCallback {
    public void setParameter(ParameterSetter setter, Object parameter) throws SQLException {
        setter.setString(parameter == null ? null : ((PartyType)parameter).getCode());

    public Object getResult(ResultGetter getter) throws SQLException {
        return valueOf(getter.getString());

    public Object valueOf(String s) {
        return s == null ? null : PartyType.find(s);

There are two ways that a type handler can be used: locally or globally.

A global type handler is placed in the Ibatis config file. Currently this is sqlmap-config.xml. It would change the file to this:

    <typeHandler javaType="com.cforcoding.PartyType" callback="com.cforcoding.PartyTypeHandler"/>
    <sqlMap resource="com/cforcoding/Party.xml"/>

Alternatively, it can be used locally, meaning within an explicit result map or parameter map or within an implicit parameter map. We have not used explicit result mapping yet. It looks like this:

<resultMap id="party" class="com.cforcoding.Party">
    <result property="id" column="ID"/>
    <result property="type" column="party_type" typeHandler="com.cforcoding.PartyTypeHandler"/>
    <result property="name" column="NAME"/>

<select id="selectAllParties" resultMap="party">
    SELECT id, party_type, name
    FROM party

Explicit result maps allow you more control but are also more verbose. In the interests of brevity, they should generally only be used when you need to use them.

OK, so where's the inheritance?

In the first tutorial, we developed a simple query for selecting a specific person. In this one, we have a query for returning all parties. But let's say we have returned a list of parties and know whether they are people or companies. With only the party object we would need to do a query for each party record to get additional Person or Company details (or use some convoluted IN clause). We have a simple object hierarchy:

  • Party
  • Person extends Party
  • Company extends Party

As it turns out, we need explicit result maps to implement this inheritance structure.


package com.cforcoding;

import java.sql.Date;

public class Person extends Party {
    private String title;
    private String givenNames;
    private String lastName;
    private Date dateOfBirth;

    public String getTitle() { return title; }
    public void setTitle(String title) { this.title = title; }
    public String getGivenNames() { return givenNames; }
    public void setGivenNames(String givenNames) { this.givenNames = givenNames; }
    public String getLastName() { return lastName; }
    public void setLastName(String lastName) { this.lastName = lastName; }
    public Date getDateOfBirth() { return dateOfBirth; }
    public void setDateOfBirth(Date dateOfBirth) { this.dateOfBirth = dateOfBirth; }
Note: Now Person extends the Party class.


package com.cforcoding;

public class Company extends Party {
    private String comapnyNumber;
    private String stateOfIncorporation;

    public String getComapnyNumber() { return comapnyNumber; }
    public void setComapnyNumber(String comapnyNumber) { this.comapnyNumber = comapnyNumber; }
    public String getStateOfIncorporation() { return stateOfIncorporation; }
    public void setStateOfIncorporation(String stateOfIncorporation) { this.stateOfIncorporation = stateOfIncorporation; }


<resultMap id="party" class="com.cforcoding.Party">
    <result property="id" column="ID"/>
    <result property="type" column="party_type" typeHandler="com.cforcoding.PartyTypeHandler"/>
    <result property="name" column="NAME"/>
    <discriminator javaType="com.cforcoding.PartyType" column="PARTY_TYPE" typeHandler="com.cforcoding.PartyTypeHandler">
        <subMap value="PERSON" resultMap="person"/>
        <subMap value="COMPANY" resultMap="company"/>

<resultMap id="person" class="com.cforcoding.Person" extends="party">
    <result property="title" column="TITLE"/>
    <result property="givenNames" column="GIVEN_NAMES"/>
    <result property="lastName" column="LAST_NAME"/>
    <result property="dateOfBirth" column="DATE_OF_BIRTH"/>

<resultMap id="company" class="com.cforcoding.Company" extends="party">
    <result property="comapnyNumber" column="COMPANY_NUMBER"/>
    <result property="stateOfIncorporation" column="STATE_OF_INCORPORATION"/>

<select id="selectAllParties" resultMap="party">
    SELECT pt.id, party_type, name, title, given_names, last_name, date_of_birth, company_number, state_of_incorporation
    FROM party pt
    LEFT OUTER JOIN person ps ON pt.id = ps.id
    LEFT OUTER JOIN company c ON pt.id = c.id

This is where it gets interesting. There are a number of new features here:

  1. Result maps can extend other result maps. Note: No inheritance is implied by result map extension. It is probably more accurate to describe it as inclusion rather than extension as it simply avoids having to copy-and-paste the result definitions;
  2. There is now a <discriminator> element in the party result map. The discriminator column declares which column will determine what type each row from the result set will be. The values are enumerated as <subMap> child elements;
  3. The sub-maps extend the party result map but this is not required. It is however--in this case at least--a convenience. Remember result map extension is not quite the same thing as object inheritance even though the two will tend to go hand in hand;
  4. A type handler is used on the discriminator so the values can be enum values. An equally valid strategy would've been to leave them as strings and use the codes P and C. You can use whichever approach you prefer.

And that's it. It's as straightforward as that. The unfortunate part of this is that the above behaviour isn't documented in the Ibatis reference PDF.

Compared to JPA

Those of you familiar with JPA will find the above familiar. Party is a mapped superclass. The behaviour models the joined table inheritance strategy. In JPA parlance, party type is also a discriminator column.

JPA providers vary in how they handled the joined table scenario from a SQL point of view. Depending on the provider and the number of subclasses the provider will either use a left outer join as we have done. Alternatively, the provider may opt to get all the parties in one query and, depending on query hints and the like, may get all the persons in the second query and all the companies in the third. This is certainly how EclipseLink operates in batch mode, which can be a powerful alternative, particularly if the number of subclasses is large.

Interestingly, Ibatis is more flexible than standard JPA with enum handling. Standard JPA does not have a means of doing custom type conversion. Standard JPA has only two ways of treating enums: by their name() or by their ordinal(). This is one part of JPA I find highly unsatisfactory as using one-character codes is a common idiom in databases. While you can use one letter names for your enum values, this does not lend itself to readable code, particularly if combined with static imports.

Individual providers may have proprietary extensions to go beyond standard JPA, such as custom type mapping or overriding the SQL dialect.

JPA's inheritance strategies also apply to database writes whereas that behaviour isn't quite as straightforward in Ibatis. Updates and inserts are probably best handled via the somewhat ugly use of instanceof.


Inheritance mapping is a powerful and useful feature of any persistence framework. It's not well-known--and certainly not well-documented--that Ibatis has this feature. It's features like this that, for me, enable Ibatis to pull ahead of other lower-level frameworks like Spring JDBC.

I believe that Ibatis really is on the "sweet spot" of complexity vs capability for persistence frameworks, offering most of the (useful) features of JPA with significantly less complexity. This tutorial is another in the series that I hope will demonstrate that.


jim said...
This comment has been removed by a blog administrator.
Anonymous said...

Wow! this is a great piece of work. Thank you very much for this insight. I'm building a desktop application using both Spring and iBatis. I must admit I found your topic to be very useful. Once again thank you for your efforts.

Anonymous said...

The book "IBatis in Action" from Manning covers the topic of mapping inheritance in chapter 6.3.1. I don't want to do some advertisment, sorry.

Anonymous said...

Thanks for the post. This post was very well explained.

Anonymous said...

how about when you do an update? don't you have to convert the field? i,e.:

update id=...
party_type = #type.code#

Post a Comment