How do I create MyBatis mapper?

In this example you will see how to create or define a data mapper using the MyBatis. The mapper will communicate our application with the underlying databases where the data is stored. MyBatis data mapper is defined as an interface object. We can either use annotations or the xml mapper to define our database query.

In the first steps we will create a domain object, a simple pojo to store our data in the object world. The attributes / fields of our pojo resemble the structure of our records table in the database.

package org.kodejava.mybatis.support;

import java.io.Serializable;
import java.util.Date;

public class Record implements Serializable {
    private Long id;
    private String title;
    private Date releaseDate;
    private Long artistId;
    private Long labelId;

    // Getters & Setters

    @Override
    public String toString() {
        return "Record{" +
            "id=" + id +
            ", title='" + title + '\'' +
            ", releaseDate=" + releaseDate +
            ", artistId=" + artistId +
            ", labelId=" + labelId +
            '}';
    }
}

Next we define the mapper interface code, we’ll create a RecordMapper.java file that contains a method to get data from the table. At this time the interface will be as the following:

package org.kodejava.mybatis;

import org.kodejava.mybatis.support.Record;

public interface RecordMapper {
    /**
     * Get a single Record from the database based on the record
     * identified.
     * 
     * @param id record identifier.
     * @return a record object.
     */
    Record getRecord(Long id);
}

After create the ResultMapper.java interface we create a RecordMapper.xml file that defines the queries used by our mapper. Here is how it looks like:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.kodejava.mybatis.RecordMapper">

    <resultMap id="recordResultMap" type="record">
        <result column="id" property="id"/>
        <result column="title" property="title"/>
        <result column="release_date" property="releaseDate"/>
        <result column="artist_id" property="artistId"/>
        <result column="label_id" property="labelId"/>
    </resultMap>

    <select id="getRecord" parameterType="java.lang.Long" resultMap="recordResultMap">
        SELECT id,
            title,
            release_date,
            artist_id,
            label_id
        FROM record
        WHERE id = #{id}
    </select>
</mapper>

To tell MyBatis about our mapper we need to define the mapper inside MyBatis configuration file (resources/configuration.xml). We register the mapper inside the <mappers> element of the configuration file.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <typeAliases>
        <typeAlias alias="record" type="org.kodejava.mybatis.support.Record" />
    </typeAliases>
    <environments default="dev">
        <environment id="dev">
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver" />
                <property name="url" value="jdbc:mysql://localhost/musicdb" />
                <property name="username" value="music" />
                <property name="password" value="s3cr*t" />
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="org/kodejava/mybatis/mapper/RecordMapper.xml" />
    </mappers>
</configuration>

Finally, we create a simple application to use the data mapper to get record data from the database.

package org.kodejava.mybatis;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.kodejava.mybatis.support.Record;

import java.io.Reader;

public class MusicClient {

    public static void main(String[] args) throws Exception {
        Reader reader = Resources.getResourceAsReader("configuration.xml");

        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(reader);

        try (SqlSession session = factory.openSession()) {
            RecordMapper mapper = session.getMapper(RecordMapper.class);
            Record record = mapper.getRecord(1L);
            System.out.println("Record = " + record);
        }
    }
}

Maven Dependencies

<dependencies>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.13</version>
    </dependency>
    <dependency>
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
        <version>8.1.0</version>
    </dependency>
</dependencies>

Maven Central Maven Central

How do I create MyBatis SqlSession object?

To create an SqlSession you can use the SqlSessionFactory class openSession() method. This method offers some overloaded method that can configure the property of the session. For example, we can configure the auto-commit-mode and the transaction-isolation-level for the session.

package org.kodejava.mybatis;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.kodejava.mybatis.support.Record;

import java.io.IOException;
import java.io.Reader;

public class SqlSessionDemo {

    public static void main(String[] args) throws IOException {
        SqlSessionDemo demo = new SqlSessionDemo();

        // Build an SqlSessionFactory.
        SqlSessionFactory factory = demo.getSessionFactory();

        // Create an SqlSession by using the factory.openSession() method.
        // It is a good practice to use a try-with-resources block when
        // working with an SqlSession. The session will be automatically
        // closes when it finishes the job.
        try (SqlSession session = factory.openSession()) {
            Record record = session.selectOne("getRecord", 1L);
            System.out.println("Record = " + record);
        }
    }

    /**
     * Build an SqlSessionFactory.
     *
     * @return an SqlSessionFactory.
     * @throws IOException when fail to read the configuration file.
     */
    private SqlSessionFactory getSessionFactory() throws IOException {
        Reader reader = Resources.getResourceAsReader("configuration.xml");
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        return builder.build(reader);
    }
}

Below are the configuration, mapper and the POJO.

  • configuration.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <typeAliases>
        <typeAlias alias="record" type="org.kodejava.mybatis.support.Record" />
    </typeAliases>
    <environments default="dev">
        <environment id="dev">
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver" />
                <property name="url" value="jdbc:mysql://localhost/musicdb" />
                <property name="username" value="music" />
                <property name="password" value="s3cr*t" />
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="org/kodejava/mybatis/mapper/RecordMapper.xml" />
    </mappers>
</configuration>
  • RecordMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.kodejava.mybatis.RecordMapper">

    <resultMap id="recordResultMap" type="record">
        <result column="id" property="id" />
        <result column="title" property="title" />
        <result column="release_date" property="releaseDate" />
        <result column="artist_id" property="artistId" />
        <result column="label_id" property="labelId" />
    </resultMap>

    <select id="getRecord" parameterType="java.lang.Long" resultMap="recordResultMap">
        SELECT id,
            title,
            release_date,
            artist_id,
            label_id
        FROM record
        WHERE id = #{id}
    </select>
</mapper>
  • Record.java
package org.kodejava.mybatis.support;

import java.io.Serializable;
import java.util.Date;

public class Record implements Serializable {
    private Long id;
    private String title;
    private Date releaseDate;
    private Long artistId;
    private Long labelId;

    // Getters & Setters

    @Override
    public String toString() {
        return "Record{" +
                "id=" + id +
                ", title='" + title + '\'' +
                ", releaseDate=" + releaseDate +
                ", artistId=" + artistId +
                ", labelId=" + labelId +
                '}';
    }
}

The directory structure of the code above is:

├─ pom.xml
└─ src
   └─ main
      ├─ java
      │  └─ org
      │     └─ kodejava
      │        └─ mybatis
      │           ├─ SqlSessionDemo.java
      │           └─ domain
      │              └─ Record.java
      └─ resources
            ├─ configuration.xml
            └─ org
               └─ kodejava
                  └─ mybatis
                     └─ mapper
                        └─ RecordMapper.xml

Maven Dependencies

<dependencies>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.13</version>
    </dependency>
    <dependency>
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
        <version>8.1.0</version>
    </dependency>
</dependencies>

Maven Central Maven Central

How do I create an SqlSessionFactory object in MyBatis?

The example below shows you how to create MyBatis SqlSessionFactory object using an XML configuration. The steps required is to create the configuration file. This file basically contains the connection information to the database and MyBatis configuration such as typeAliases and the mappers.

The next steps is to read the configuration file using a org.apache.ibatis.io.Resources class. This information then passes as the argument to the build() method of the SqlSessionFactoryBuilder class. The build() method return an SqlSessionFactory object.

package org.kodejava.mybatis;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.kodejava.mybatis.support.Record;

import java.io.IOException;
import java.io.Reader;

public class SqlSessionFactoryDemo {

    public static void main(String[] args) throws IOException {
        // A resource file for MyBatis configuration.
        Reader reader = Resources.getResourceAsReader("configuration.xml");

        // Creates an SqlSessionFactoryBuilder. This builder need only 
        // create one time during the application lifetime.
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();

        // Creates an instance of SqlSessionFactory. This object can be 
        // used to initiate an SqlSession for querying information from 
        // the mapped query.
        SqlSessionFactory factory = builder.build(reader);
        System.out.println("factory = " + factory);

        try (SqlSession session = factory.openSession()) {
            RecordMapper mapper = session.getMapper(RecordMapper.class);
            Record record = mapper.getRecord(1L);
            System.out.println("Record = " + record);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Below is an example of MyBatis configuration file:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <typeAliases>
        <typeAlias alias="record" type="org.kodejava.mybatis.support.Record" />
    </typeAliases>
    <environments default="dev">
        <environment id="dev">
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver" />
                <property name="url" value="jdbc:mysql://localhost/musicdb" />
                <property name="username" value="music" />
                <property name="password" value="s3cr*t" />
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="org/kodejava/mybatis/mapper/RecordMapper.xml" />
    </mappers>
</configuration>

Below are the other supporting files and classes for the code above, RecordMapper.xml, RecordMapper and Record.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.kodejava.mybatis.RecordMapper">

    <resultMap id="recordResultMap" type="record">
        <result column="id" property="id"/>
        <result column="title" property="title"/>
        <result column="release_date" property="releaseDate"/>
        <result column="artist_id" property="artistId"/>
        <result column="label_id" property="labelId"/>
    </resultMap>

    <select id="getRecord" parameterType="java.lang.Long" resultMap="recordResultMap">
        SELECT id,
            title,
            release_date,
            artist_id,
            label_id
        FROM record
        WHERE id = #{id}
    </select>
</mapper>
package org.kodejava.mybatis;

import org.kodejava.mybatis.support.Record;

public interface RecordMapper {
    /**
     * Get a single record from the database based on the record
     * identifier.
     *
     * @param id record identifier.
     * @return a record object.
     */
    Record getRecord(Long id);
}
package org.kodejava.mybatis.support;

import java.io.Serializable;
import java.util.Date;

public class Record implements Serializable {
    private Long id;
    private String title;
    private Date releaseDate;
    private Long artistId;
    private Long labelId;

    // Getters & Setters

    @Override
    public String toString() {
        return "Record{" +
                "id=" + id +
                ", title='" + title + '\'' +
                ", releaseDate=" + releaseDate +
                ", artistId=" + artistId +
                ", labelId=" + labelId +
                '}';
    }
}

Maven Dependencies

<dependencies>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.13</version>
    </dependency>
    <dependency>
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
        <version>8.1.0</version>
    </dependency>
</dependencies>

Maven Central Maven Central

How do I capitalize each word in a string?

This example show you how to capitalize a string. We use methods from WordUtils class provided by the Apache commons-text;. We can use the WordUtils.capitalize(str) or WordUtils.capitalizeFully(str).

Let’s see an example below:

package org.kodejava.commons.text;

import org.apache.commons.text.WordUtils;

public class WordCapitalize {
    public static void main(String[] args) {
        // Capitalizes all the whitespace separated words in a string,
        // only the first letter of each word is capitalized.
        String str = WordUtils.capitalize(
                "The quick brown fox JUMPS OVER the lazy dog.");
        System.out.println("str = " + str);

        // Capitalizes all the whitespace separated words in a string
        // and the rest string to lowercase.
        str = WordUtils.capitalizeFully(
                "The quick brown fox JUMPS OVER the lazy dog.");
        System.out.println("str = " + str);
    }
}

And here are the result of the program:

str = The Quick Brown Fox JUMPS OVER The Lazy Dog.
str = The Quick Brown Fox Jumps Over The Lazy Dog.

Maven Dependencies

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-text</artifactId>
    <version>1.12.0</version>
</dependency>

Maven Central

How do I create a thread synchronized block?

The objective of thread synchronization is to ensure that when several threads want access to a single resource, only one thread can access it at any given time.

You can manage synchronization of your program at method level (synchronized method) or at block level (synchronized block). To make a block of code synchronized you can use the synchronized keyword.

The example below show how you can use the synchronized keyword.

  • Incrementor class
package org.kodejava.lang;

public class Incrementor {
    private int count;

    // A synchronized method example.
    public synchronized void increment(int value) {
        count += value;
        System.out.println(Thread.currentThread().getName() +
                ": inc >>> " + count);
    }

    public void decrement(int value) {
        // A synchronized block example the use the current object instance
        // as the monitor object.
        synchronized (this) {
            count -= value;
            System.out.println(Thread.currentThread().getName() +
                    ": dec >>> " + count);
        }
    }
}
  • IncrementThread class
package org.kodejava.lang;

public class IncrementThread implements Runnable {
    private final Incrementor incrementor;

    public IncrementThread(Incrementor incrementor) {
        this.incrementor = incrementor;
    }

    public void run() {
        for (int i = 1; i <= 5; i++) {
            incrementor.increment(i * 10);
            incrementor.decrement(i * 2);

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
  • IncrementorDemo class
package org.kodejava.lang;

public class IncrementorDemo {
    public static void main(String[] args) {
        Incrementor incrementor = new Incrementor();

        Thread t1 = new Thread(new IncrementThread(incrementor), "T1");
        Thread t2 = new Thread(new IncrementThread(incrementor), "T2");

        t1.start();
        t2.start();
    }
}

Here an example result printed by the program:

T1: inc >>> 10
T1: dec >>> 8
T2: inc >>> 18
T2: dec >>> 16
T1: inc >>> 36
T1: dec >>> 32
T2: inc >>> 52
T2: dec >>> 48
T1: inc >>> 78
T1: dec >>> 72
T2: inc >>> 102
T2: dec >>> 96
T1: inc >>> 136
T1: dec >>> 128
T2: inc >>> 168
T2: dec >>> 160
T1: inc >>> 210
T1: dec >>> 200
T2: inc >>> 250
T2: dec >>> 240