Manual

This manual covers the configuration of iBatis Java Mapper with Spring, and the creation of result maps and mapped statements. The examples are modifications of the JPetStore application which is bundled with both iBatis and Spring. The modified example can also be found as part of iBatis Java MApper sources.

Note: this manual assumes you are familiar with iBatis and its configuration with Spring .

Configuration with Spring

The first thing you need to do in order to use iBatis Java Mapper is to configure it with Spring. The configuration is very similar to the configuration of iBatis with Spring:

...

<bean id="sqlMapClient" class="net.sf.javamapper.factory.JavaSqlMapClientFactoryBean">
        <property name="configLocation" value="classpath:sql-map-config.xml" />
        <property name="dataSource" ref="dataSource" />
        <property name="mapperClasses">
                <list>
                        <value>net.sf.javamapper.jpetstore.dao.ibatis.mapperclasses.AccountMapper</value>
                </list>
        </property>
</bean>

...

The above code configures iBatis with the Java Mapper extension. Don't forget to configure the data source and transaction manager according to your requirements as explained in the Spring reference. The new thing here is the mapperClass parameter which receives a collection of all the classes and/or interfaces that define object-SQL mappings.

Creating Result Maps

The iBatis Java Mapper version of result maps is classes annotated with the @ResultMap annotation, with getter methods that correspond to the mapped propertied and are annotated with @Result . The @Result annotation defines the mapped column and whether the property is used by the result map's groupBy property. To make things clear, instead of defining a result map with the following XML:

<resultMap id="AccountMapper" class="org.springframework.samples.jpetstore.domain.Account" groupBy="username">
        <result property="username" column="userid"/>
        <result property="email" column="email"/>
</resulrMap>

We could define the following mapper class:

@ResultMap(resultClass=Account.class)
public abstract class AccountMapper extends Account { 

        @Override
        @Result(column="userid", groupBy=true)
        public abstract String getUsername();
        
        @Override
        @Result(column="email")
        public abstract String getEmail();
}

In the above example AccountMapper extends Account, which is also the result class. This approach is recommended if you can't/won't add Java Mapper annotations to your domain classes. It would be simpler to use the Account class as its own mapper like so:

@ResultMap {
public class Account {

        private String username;
        private String email;

        @Result(column="userid", groupBy=true)
        public String getUsername();
        
        @Result(column="email")
        public String getEmail();
        
        // Setters ...
}

Looks pretty much like a JPA Entity, isn't it? When you don't provide a value to the @ResultMap resultClass attribute, iBatis Java Mapper uses the mapper class itself as the result class.

It is possible to use a class or interface which is unrelated to the domain class which is used as the result class, but it is not recommended because at compile time you can't be certain that the result maper class's getters are the same as those of the result class.

Since the result map ID is the class simple name (without the package), these result maps can also be used for mapped statements which are defined in iBatis XML maps.

Creating Mapped Statements

iBatis Java Mapper uses methods to map statements. Statement methods can be in classes and interfaces with or without the @ResultMap annotation, it doesn't matter. Methods are used for statement mapping if they are annotated with @Select, @Insert, @Update or @Delete.

Here is an example of a mapped select statement:

@Select("select username as value from signon")
public abstract String getUsernameList();

In this case the SQL is provided as the value of the @Select annotation. It is also possible to use a properties file to hold the SQL if you don't want it in the Java source. The properties file's path and name must match the class/interface full name, for example if the class containing the mapper method is named foo.bar.MapperClass , then its matching properties file must be /foo/bar/MapperClass.properties . The entry key is the method name and the entry value is the SQL:

getUsernameList = select username as value from signon

Now we can write the annotation without the SQL:

@Select
public abstract String getUsernameList();

Let's take a look at the method signiture and see what iBatis Java Mapper can learn from it about the required mapping. The return type is String , so this is the class which is used as the statement result class. Now let's look at another example:

@Select(resultClassMapper=AccountMapper.class)
public abstract Account getAccountByUsernameAndPassword(Account account);

Here the annotation specifies the class that contains the result map definition. In this case the return value is ignored, but we left it as sort of self-documenting code. This method also has an argument of type Account , so Account is used as parameterClass. If a method has more than one argument, iBatis Java Mapper uses the first one as parameter class and ignores the rest.

Mapping of insert, update and delete statements is similar and even a little simpler. Here are some examples:

@Insert
public abstract void insertProfile(Account account);

@Update
public abstract void updateProfile(Account account);

@Delete
public abstract void deleteProfile(Account account);

More to come

The manual will grow as new features are added.