How to Integrate MyBatis XML with Spring Boot 2.x: A Step‑by‑Step Guide

This tutorial walks you through integrating MyBatis XML configuration into a Spring Boot 2.x project, covering Maven dependencies, application properties, mapper XML files, entity and mapper definitions, service implementation, and unit testing with full code examples.

Senior Brother's Insights
Senior Brother's Insights
Senior Brother's Insights
How to Integrate MyBatis XML with Spring Boot 2.x: A Step‑by‑Step Guide

MyBatis is a popular persistence framework in Asia, especially in China, offering custom SQL, stored procedures, and advanced mapping while eliminating most JDBC boilerplate. This guide demonstrates how to integrate MyBatis XML configuration into a Spring Boot 2.x application.

Project Dependencies

Add the following dependencies to pom.xml (Spring Boot 2.2.2, Java 1.8):

<project xmlns="http://maven.apache.org/POM/4.0.0" ...>
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.2.RELEASE</version>
  </parent>
  <groupId>com.secbro</groupId>
  <artifactId>springboot-mybatis-xml</artifactId>
  <version>0.0.1‑SNAPSHOT</version>
  <properties>
    <java.version>1.8</java.version>
  </properties>
  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
      <groupId>org.mybatis.spring.boot</groupId>
      <artifactId>mybatis-spring-boot-starter</artifactId>
      <version>2.1.1</version>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
      <exclusions>
        <exclusion>
          <groupId>org.junit.vintage</groupId>
          <artifactId>junit-vintage-engine</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>
</project>

Configuration Files

Add the following to application.properties to configure the datasource and MyBatis locations:

spring.datasource.url=jdbc:mysql://localhost:3306/spring?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# MyBatis mapper XML location
mybatis.mapper-locations=classpath:mappers/*.xml
# Package for type aliases (entity classes)
mybatis.type-aliases-package=com.secbro.model

You can also specify a global MyBatis config file with:

mybatis.config-location=classpath:mybatis/mybatis-config.xml

Application Entry Point

Enable mapper scanning by adding @MapperScan("com.secbro.mapper") to the main class:

@SpringBootApplication
@MapperScan("com.secbro.mapper")
public class SpringBootMainApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootMainApplication.class, args);
    }
}

Entity and Mapper Definitions

Entity class Order (using Lombok @Data for getters/setters):

@Data
public class Order {
    private int id;
    private String orderNo;
    private int amount;
}

Mapper interface OrderMapper defines CRUD methods:

public interface OrderMapper {
    int save(Order order);
    int update(Order order);
    int delete(int id);
    Order findById(int id);
    List<Order> findAll();
}

Corresponding XML OrderMapper.xml (placed under resources/mappers) maps SQL statements to the methods:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.secbro.mapper.OrderMapper">
    <resultMap id="BaseResultMap" type="com.secbro.model.Order">
        <id column="id" property="id" jdbcType="INTEGER" />
        <result column="order_no" property="orderNo" jdbcType="VARCHAR" />
        <result column="amount" property="amount" jdbcType="INTEGER" />
    </resultMap>
    <sql id="Base_Column_List">id, order_no, amount</sql>
    <insert id="save" parameterType="com.secbro.model.Order">
        INSERT INTO tb_order (order_no, amount) VALUES (#{orderNo}, #{amount})
    </insert>
    <update id="update" parameterType="com.secbro.model.Order">
        UPDATE tb_order
        <set>
            <if test="orderNo != null">order_no = #{orderNo},</if>
            <if test="amount != null">amount = #{amount},</if>
        </set>
        WHERE id = #{id}
    </update>
    <delete id="delete" parameterType="int">
        DELETE FROM tb_order WHERE id = #{id}
    </delete>
    <select id="findById" parameterType="int" resultMap="BaseResultMap">
        SELECT <include refid="Base_Column_List" /> FROM tb_order WHERE id = #{id}
    </select>
    <select id="findAll" resultMap="BaseResultMap">
        SELECT <include refid="Base_Column_List" /> FROM tb_order
    </select>
</mapper>

Service Layer

Define OrderService interface mirroring the mapper methods, then implement it by injecting OrderMapper with @Resource:

public interface OrderService {
    int save(Order order);
    int update(Order order);
    int delete(int id);
    Order findById(int id);
    List<Order> findAll();
}

@Service("orderService")
public class OrderServiceImpl implements OrderService {
    @Resource
    private OrderMapper orderMapper;
    @Override public int save(Order order) { return orderMapper.save(order); }
    @Override public int update(Order order) { return orderMapper.update(order); }
    @Override public int delete(int id) { return orderMapper.delete(id); }
    @Override public Order findById(int id) { return orderMapper.findById(id); }
    @Override public List<Order> findAll() { return orderMapper.findAll(); }
}

Unit Tests

Use SpringBootTest with Lombok @Slf4j to verify CRUD operations:

@Slf4j
@SpringBootTest
class OrderServiceTest {
    @Resource
    private OrderService orderService;

    @Test
    void save() {
        for (int i = 1; i <= 3; i++) {
            Order order = new Order();
            order.setOrderNo("N00" + i);
            order.setAmount(10000);
            orderService.save(order);
        }
    }

    @Test
    void update() {
        Order order = new Order();
        order.setId(1);
        order.setOrderNo("N001");
        order.setAmount(8888);
        orderService.update(order);
    }

    @Test
    void delete() { orderService.delete(2); }

    @Test
    void findById() {
        Order order = orderService.findById(3);
        log.info("Order: {}", order);
    }

    @Test
    void findAll() {
        List<Order> list = orderService.findAll();
        log.info("All orders: {}", list);
    }
}

After completing these steps, the Spring Boot application is fully integrated with MyBatis XML, ready for further business development.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Javaunit testingSpring BootPersistenceMyBatisCRUDXML Mapper
Senior Brother's Insights
Written by

Senior Brother's Insights

A public account focused on workplace, career growth, team management, and self-improvement. The author is the writer of books including 'SpringBoot Technology Insider' and 'Drools 8 Rule Engine: Core Technology and Practice'.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.