# Extending the Example Classes

In some cases it may be desirable to extended the generated example classes. You may want to add criterion that are specific to your database (such as Oracle ROWNUM support), or add criterion that are not automatically generated (such as a case insensitive search). In situations like these, you may extend the generated example class to add these additional criteria.

## General Principles

MyBatis Generator (MBG) generates an "example" class for each table, unless instructed otherwise in the configuration. The "example" class is used to generate a dynamic where clause for use in the `xxxByExample` statements. The standard "example" class includes functionality for all standard SQL predicates. In some cases, it may be desirable to add additional predicates for the specific needs of your application. This may include adding support for non-standard predicates, or for using database specific functions in your where clauses.

The generated "example" class includes a nested inner class where the actual functionality of the predicates exists. This inner class is always named `GeneratedCriteria`. MBG also generates an inner class named `Criteria` which extends `GeneratedCriteria` and which you may use for adding your own functions to the example classes. The `Criteria` class will not be deleted by the Eclipse Java code merger, so you may add to it without fear of losing your changes upon regeneration.

For example, suppose there is a table called CUSTOMER. Typically, MBG would generate a class named `CustomerExample`. To add functionality to the `CustomerExample` class, you should add additional methods to the `CustomerExample.Criteria` class.

## Extending vs. Plugging In

If you find that you are extending the example classes frequently, it might be more convenient for you to create a plugin to generate the additional functionality rather than hand coding the extended classes. The example below (under the heading "Single Parameter Predicates") can also be accomplished with a plugin as demonstrated by the class `org.mybatis.generator.plugins.CaseInsensitiveLikePlugin`.

## Adding Predicates

MBG generates a dynamic SQL fragment that allows virtually unlimited where clauses to be created at run-time. To accomplish this, the generated SQL fragment supports four broad types of SQL predicates. For each type of SQL predicate, there is a corresponding method in the `GeneratedCriteria` inner class that can be used to add a predicate to the dynamic where clause.

### 1. Simple String Substitution

This type of predicate is used when there is no need for a property from the parameter object to be substituted into the where clause. Examples include:

`FIRST_NAME is null`
`LAST_NAME is not null`

The `GeneratedCriteria` class method for this predicate is:

`addCriterion(String anyString)`

Where "anyString" is the string to be substituted into the where clauses. This method can be used to add any kind of test to the generated where clause.

For example, suppose you wanted to use the SOUNDEX function to do a "sounds like" name search. In MySQL, the predicate should look like this:

`SOUNDEX(FIRST_NAME) = SOUNDEX('frod')`

This predicate is too complex to use one of the other methods, so it must be inserted into the where clause by simple string substitution. Add the following method to the `Criteria` inner class for this functionality:

    public Criteria andFirstNameSoundsLike(String value) {
      StringBuffer sb = new StringBuffer("SOUNDEX(FIRST_NAME) = SOUNDEX('");
      sb.append(value);
      sb.append("')");

      addCriterion(sb.toString());

      return this;
    }

The following code shows the use of this new functionality with the `selectByExample` method:

    CustomerExample example = new CustomerExample();
    Criteria criteria = example.createCriteria();
    criteria.andFirstNameSoundsLike("frod");
    List results = selectByExample(example);

This method can be used to add virtually any predicate to a where clause. However, it is generally better to use parameter substitution if possible because the problems of formatting different data types properly (most notably dates, times, and timestamps). Also, there is a chance of SQL injection issues with this method if you expose a too generic method. If possible, we suggest using one of the other methods listed below.

### 2. Single Parameter Predicates

This type of predicate is used when there is a single property from the parameter object to be substituted into the where clause. Examples include

`FIRST_NAME = ?`
`LAST_NAME <> ?`

The generated `Criteria` class method for this predicate is:

`addCriterion(String anyString, Object anyObject, String propertyName)`

Where:

anyString
  is the string to be substituted into the where clause before a parameter substitution
anyObject
  is the Object to be substituted into the where clause after the string substitution
propertyName
  is a string denoting the property name related to this clause. This String is only used in potential error messages.

This method can be used to add simple tests related to a single parameter to the generated where clause.

For example, suppose you wanted to perform a case insensitive search on certain columns. In MySQL, the predicate could look like this:

`upper(FIRST_NAME) like ?`

This predicate fits the capabilities of a single parameter predicate - where the predicate is a string value followed by a single parameter. Add the following method to the `ExtendedCriteria` for this functionality:

    public ExtendedCriteria andFirstNameLikeInsensitive(String value) {
      addCriterion("upper(FIRST_NAME) like",
        value.toUpperCase(), "firstName");

      return this;
    }

The following code shows the use of this new functionality with the `selectByExample` method:

    ExtendedExample example = new ExtendedExample();
    ExtendedCriteria criteria = (ExtendedCriteria) example.createCriteria();
    criteria.andFirstNameLikeInsensitive("fred%");
    List results = selectByExample(example);

### 3. List Predicates

List predicates are used to add a variable sized list of values as parameters to a where clause. Examples include:

`FIRST_NAME IN (?, ?, ?)`
`LAST_NAME NOT IN (?, ?, ?, ?)`

This predicate is less flexible then the others because it is included specifically for the "in" and "not in" standard predicates. Nevertheless, if you find some use for it the corresponding method in the `Criteria` class is as follows:

`addCriterion(String anyString, List listOfObjects, String propertyName)`

Where:

anyString
  is the string to be substituted into the where clause before a parameter substitution
listOfObjects
  is the List of Objects to be substituted into the where clause after the string substitution (an open parenthesis will be appended before the list, list items will be comma delimited, and a close parenthesis will be appended after the list).
propertyName
  is a string denoting the property name related to this clause. This String is only used in potential error messages.

### 4. Between Predicates

Between predicates are used to add a two parameters to a where clause in a specific format. Examples include:

`FIRST_NAME BETWEEN ? AND ?`
`LAST_NAME NOT BETWEEN ? AND ?`

This predicate is less flexible then the others because it is included specifically for the "between" and "not between" standard predicates. Nevertheless, if you find some use for it the corresponding method in the `Criteria` class is as follows:

`addCriterion(String anyString, Object object1, Object object2, String propertyName)`

Where:

anyString
  is the string to be substituted into the where clause before a parameter substitution
object1
  is the objects to be substituted into the where clause after the string substitution (the word "and" will be appended after this object).
object2
  is the objects to be substituted into the where clause after the word "and".
propertyName
  is a string denoting the property name related to this clause. This String is only used in potential error messages.