Step-by-Step Guide to Building a Spring Boot Application with MyBatis and MySQL

This tutorial walks through creating a Spring Boot project, configuring Maven dependencies, setting up MySQL with MyBatis, defining entity, mapper, service, and controller layers, and building simple Thymeleaf login and registration pages, culminating in a runnable dynamic authentication demo.

Java Captain
Java Captain
Java Captain
Step-by-Step Guide to Building a Spring Boot Application with MyBatis and MySQL

First, create a Spring Boot project using Spring Initializr, selecting the dependencies Spring Web, Thymeleaf, JDBC API, Spring Data JDBC, and MySQL Driver.

Next, add the required Maven dependencies in pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>springboot-web04</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.3</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.1</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.6</version>
        </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>

Configure the data source in application.yml (or application.properties) to point to a MySQL database named mybatis:

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=GMT%2B8&useSSL=true
    username: root  # database user
    password: sm1208  # password
# application.properties example
server.port=8080
spring.thymeleaf.cache=false
mybatis.mapper-locations=classpath:mapper/*.xml
type=com.alibaba.druid.pool.DruidDataSource

Create a simple POJO to hold login data:

package springbootweb04.demo.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserLogin {
    private String username;
    private String password;
}

Set up a MySQL database mybatis and a table userLogin with columns username and password. Connect to the database from IntelliJ IDEA via the Data Source view.

Define a MyBatis mapper interface and its XML mapping file:

package springbootweb04.demo.mapper;

import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import springbootweb04.demo.pojo.UserLogin;
import java.util.List;

@Mapper
@Repository
public interface UserLoginMapper {
    List<UserLogin> queryAll();
    int add(UserLogin userLogin);
    UserLogin queryByName(String username);
}
<?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="springbootweb04.demo.mapper.UserLoginMapper">
    <select id="queryAll" resultType="springbootweb04.demo.pojo.UserLogin">
        SELECT * FROM userLogin
    </select>
    <insert id="add" parameterType="springbootweb04.demo.pojo.UserLogin">
        INSERT INTO userLogin VALUES (#{username}, #{password})
    </insert>
    <select id="queryByName" resultType="springbootweb04.demo.pojo.UserLogin">
        SELECT * FROM userLogin WHERE username = #{username}
    </select>
</mapper>

Write a simple test to verify the datasource and mapper work:

package springbootweb04.demo;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import springbootweb04.demo.mapper.UserLoginMapper;
import springbootweb04.demo.pojo.UserLogin;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;

@SpringBootTest
class DemoApplicationTests {
    @Autowired
    DataSource dataSource;

    @Test
    void contextLoads() throws SQLException {
        System.out.println(dataSource.getClass());
        Connection connection = dataSource.getConnection();
        System.out.println(connection);
        connection.close();
    }

    @Autowired
    UserLoginMapper userLoginMapper;

    @Test
    void toTest(){
        List<UserLogin> userLogins = userLoginMapper.queryAll();
        userLogins.forEach(e -> System.out.println(e));
    }
}

Define a service interface and its implementation to encapsulate mapper calls:

package springbootweb04.demo.services;

import springbootweb04.demo.pojo.UserLogin;
import java.util.List;

public interface UserLoginServicesI {
    List<UserLogin> queryAll();
    int add(UserLogin userLogin);
    UserLogin queryByName(String username);
}
package springbootweb04.demo.services;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import springbootweb04.demo.mapper.UserLoginMapper;
import springbootweb04.demo.pojo.UserLogin;
import java.util.List;

@Service
public class UserLoginServicesImpl implements UserLoginServicesI {
    @Autowired
    UserLoginMapper userLoginMapper;

    @Override
    public List<UserLogin> queryAll() {
        return userLoginMapper.queryAll();
    }

    @Override
    public int add(UserLogin userLogin) {
        return userLoginMapper.add(userLogin);
    }

    @Override
    public UserLogin queryByName(String username) {
        return userLoginMapper.queryByName(username);
    }
}

Create a Spring MVC controller to handle login and registration requests:

package springbootweb04.demo.controller;

import springbootweb04.demo.pojo.UserLogin;
import springbootweb04.demo.services.UserLoginServicesImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class MyController {
    @Autowired
    UserLoginServicesImpl userLoginServicesImpl;

    @RequestMapping("/toLogin")
    public String toLogin(){
        return "login";
    }

    @RequestMapping("/LoginSuccess")
    public String LoginSuccess(Model model, UserLogin userLogin){
        UserLogin existing = userLoginServicesImpl.queryByName(userLogin.getUsername());
        if(existing != null){
            System.out.println(existing);
            return "success";
        } else {
            model.addAttribute("data", "User not found, please register");
            return "login";
        }
    }

    @RequestMapping("/toRegister")
    public String toRegister(){
        return "register";
    }

    @RequestMapping("/RegisterSuccess")
    public String toRegisterSuccess(Model model, UserLogin userLogin){
        userLoginServicesImpl.add(userLogin);
        System.out.println("Data inserted successfully!");
        model.addAttribute("data", "Registration successful, please log in!");
        return "login";
    }
}

Place three simple Thymeleaf templates under src/main/resources/templates:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Login</title>
</head>
<body style="background: aqua">
    <div align="center">
        <h2>Login Page</h2>
        <span th:text="${data}" style="color:red;font-size:10px"></span>
        <form method="get" action="/LoginSuccess">
            Username: <input type="text" name="username" placeholder="Enter username" required/><br/><br/>
            Password: <input type="text" name="password" placeholder="Enter password" required/><br/><br/>
            <input type="submit" value="Login"/>
        </form>
        <br/>
        <form method="get" action="/toRegister">
            <input type="submit" value="Register"/>
        </form>
    </div>
</body>
</html>
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Register</title>
</head>
<body style="background: aqua">
    <div align="center">
        <h2>Register Page</h2>
        <form method="get" action="/RegisterSuccess">
            Username: <input type="text" name="username" placeholder="Enter username" required/><br/><br/>
            Password: <input type="text" name="password" placeholder="Enter password" required/><br/><br/>
            Confirm Password: <input type="text" name="password2" placeholder="Confirm password" required/><br/><br/>
            <input type="submit" value="Register"/>
        </form>
    </div>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Success</title>
</head>
<body>
    <h2>Operation Successful</h2>
</body>
</html>

Run the application and open http://localhost:8080/toLogin to see the login page. The tutorial demonstrates a complete end‑to‑end dynamic login and registration flow using Spring Boot, MyBatis, MySQL, and Thymeleaf.

PS: If you find this guide helpful, feel free to like or share it.

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.

BackendJavaSpring BootmysqlMyBatisThymeleaf
Java Captain
Written by

Java Captain

Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.

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.