Master Spring Boot & MyBatis: Complete Setup, Mapper Scanning, and Unit Testing Guide

Learn how to configure a Spring Boot 2.3.11 project with MyBatis 3.5.6, set up dependencies, pagination, mapper scanning, define mapper interfaces with annotations, implement dynamic SQL providers, and write comprehensive unit tests to verify CRUD operations.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Master Spring Boot & MyBatis: Complete Setup, Mapper Scanning, and Unit Testing Guide

Environment

Spring Boot 2.3.11 + MyBatis 3.5.6

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.4</version>
</dependency>
<dependency>
  <groupId>com.github.pagehelper</groupId>
  <artifactId>pagehelper-spring-boot-starter</artifactId>
  <version>1.3.0</version>
</dependency>

Application Configuration

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

For detailed configuration, refer to the official documentation.

Pagination configuration:

Pagination configuration
Pagination configuration

MyBatis configuration:

MyBatis configuration
MyBatis configuration

Adding Mapper Scan to the Startup Class

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

After adding @MapperScan, individual @Mapper annotations on each mapper are unnecessary.

Core processing class: MapperScannerRegistrar.java

public class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware {
    // implementation omitted
}

The ImportBeanDefinitionRegistrar interface is used to dynamically register beans, similar to how EnableFeignClients works.

Mapper Interface Definition

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);
}

Note: Adding an id to @Results allows reuse via @ResultMap("users") in other methods. @*Provider annotations enable dynamic SQL definition.

Dynamic SQL Provider

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();
    }
}

Unit Tests

@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() + "
" + 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));
    }
}

End of tutorial.

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.

javabackend-developmentunit testingSpring BootMyBatis
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

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.