Backend Development 8 min read

Master Spring Boot & MyBatis Integration: Full Configuration and CRUD Guide

This article walks through setting up Spring Boot 2.3.11 with MyBatis 3.5.6, covering Maven dependencies, pagination and MyBatis configurations, mapper scanning, CRUD mapper definitions, dynamic SQL providers, and comprehensive unit tests, all illustrated with code snippets and diagrams.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Master Spring Boot & MyBatis Integration: Full Configuration and CRUD Guide

Environment: Spring Boot 2.3.11 + MyBatis 3.5.6

Dependencies

<code>&lt;dependency&gt;
  &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
  &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
  &lt;groupId&gt;org.mybatis.spring.boot&lt;/groupId&gt;
  &lt;artifactId&gt;mybatis-spring-boot-starter&lt;/artifactId&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
  &lt;groupId&gt;com.github.pagehelper&lt;/groupId&gt;
  &lt;artifactId&gt;pagehelper-spring-boot-starter&lt;/artifactId&gt;
  &lt;version&gt;1.3.0&lt;/version&gt;
&lt;/dependency&gt;</code>

Application Configuration

<code>pagehelper:
  helperDialect: mysql
  reasonable: true
  pageSizeZero: true
  offsetAsPageNum: true
  rowBoundsWithCount: true
---
mybatis:
  type-aliases-package: com.pack.domain
  configuration:
    lazy-loading-enabled: false
    aggressive-lazy-loading: false
    logImpl: org.apache.ibatis.logging.stdout.StdOutImpl
    mapUnderscoreToCamelCase: true</code>

Refer to the official documentation for detailed explanations of the above settings.

Pagination configuration diagram:

MyBatis configuration diagram:

Adding Mapper Scan in the Startup Class

<code>@SpringBootApplication
@MapperScan({"com.pack.mapper"})
public class SpringBootMyBatisApplication {

  public static void main(String[] args) {
    SpringApplication.run(SpringBootMyBatisApplication.class, args);
  }
}
</code>

After adding

@MapperScan

, individual mapper interfaces no longer need the

@Mapper

annotation.

Core processing class:

MapperScannerRegistrar.java
<code>public class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware {
    // implementation details omitted
}
</code>

The

ImportBeanDefinitionRegistrar

interface is used to dynamically register beans, similar to how

EnableFeignClients

registers

@FeignClient

-annotated classes.

Mapper Interface Definition

<code>public interface UsersMapper {

  @Select("SELECT * FROM t_users")
  @Results(id = "users", value = {
    @Result(property = "name", column = "name", javaType = String.class),
    @Result(property = "password", column = "password")
  })
  List<Users> findAll();

  @Select("SELECT * FROM t_users WHERE id = #{id}")
  @ResultMap("users")
  Users findById(String id);

  @Insert("insert into t_users values(#{id}, #{password}, #{username})")
  int saveUsers(Users users);

  @Update("UPDATE t_users SET username = #{username}, password = #{password} WHERE id = #{id}")
  int updateUsers(Users users);

  @Delete("DELETE FROM t_users where id = #{id}")
  int deleteById(String id);

  @SelectProvider(type = UsersProvider.class, method = "selectLikeUsers")
  @ResultMap("users")
  List<Users> selectLikeUsers(Users users);

  @UpdateProvider(type = UsersProvider.class, method = "updateByProvider")
  int updateByProvider(@Param("users") Users users);
}
</code>

Adding an

id

attribute to

@Results

allows other methods to reuse the mapping via

@ResultMap("users")

. The

@*Provider

annotations enable dynamic SQL generation.

Dynamic SQL Provider

<code>public class UsersProvider {

  public String selectLikeUsers(Users users) {
    StringBuilder sql = new StringBuilder("SELECT * FROM t_users t where 1=1 ");
    if (users.getUsername() != null && users.getUsername().trim().length() > 0) {
      sql.append(String.format("and t.username like '%s'", "%" + users.getUsername() + "%"));
    }
    return sql.toString();
  }

  public String updateByProvider(@Param("users") Users users) {
    SQL sql = new SQL();
    sql.UPDATE("t_users")
       .SET("username = #{users.username}", "password = #{users.password}")
       .WHERE("id = #{users.id}");
    return sql.toString();
  }
}
</code>

Unit Tests

<code>@RunWith(SpringRunner.class)
@SpringBootTest
public class UsersMapperTest {

  @Resource
  private UsersMapper usersMapper;

  @Test
  public void testFindAll() {
    Page<Users> page = PageHelper.startPage(1, 2);
    usersMapper.findAll();
    System.out.println(page.getResult());
    System.out.println(page.getTotal() + "\n" + page.getPages());
  }

  @Test
  public void testFindById() {
    System.out.println(usersMapper.findById("1"));
  }

  @Test
  public void testSaveUsers() {
    Users users = new Users();
    users.setId("4");
    users.setPassword("123456");
    users.setUsername("zhangsan");
    System.out.println(usersMapper.saveUsers(users));
  }

  @Test
  public void testUpdateUser() {
    Users users = new Users();
    users.setId("3");
    users.setPassword("111111");
    users.setUsername("zhangsan");
    System.out.println(usersMapper.updateUsers(users));
  }

  @Test
  public void testDeleteById() {
    System.out.println(usersMapper.deleteById("3"));
  }

  @Test
  public void testSelectLikeUsers() {
    Users users = new Users();
    users.setUsername("gu");
    System.out.println(usersMapper.selectLikeUsers(users));
  }

  @Test
  public void testUpdateByProvider() {
    Users users = new Users();
    users.setId("2");
    users.setPassword("111111");
    users.setUsername("guest");
    System.out.println(usersMapper.updateByProvider(users));
  }
}
</code>

All steps are complete.

Javaunit testingSpring BootMyBatispaginationMapper
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

login 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.