Implementing CRUD Operations with MyBatis XML Mappers

Implementing data persistence logic requires a clear mapping between Java objects and database tables. The following demonstration outlines the configuration and execution of Create, Read, Update, and Delete (CRUD) operations using MyBatis.

Entity Class Definition

First, define a Plain Old Java Object (POJO) to represent the data structure. This class will be mapped to a database table.
package com.example.mybatis.entity;

public class User {
    
    private Integer userId;
    private String username;
    private Integer age;
    private String gender;

    // Default constructor
    public User() {}

    // Constructor with fields
    public User(Integer userId, String username, Integer age, String gender) {
        this.userId = userId;
        this.username = username;
        this.age = age;
        this.gender = gender;
    }

    // Getters and Setters
    public Integer getUserId() { return userId; }
    public void setUserId(Integer userId) { this.userId = userId; }
    public String getUsername() { return username; }
    public void setUsername(String username) { this.username = username; }
    public Integer getAge() { return age; }
    public void setAge(Integer age) { this.age = age; }
    public String getGender() { return gender; }
    public void setGender(String gender) { this.gender = gender; }
}

SQL Mapper Configuration

The XML mapper file defines the SQL queries. The <mapper> namespace ensures unique identification of the statements. A <resultMap> is utilized when property names in the Java class differ from database column names.
<?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.example.mybatis.entity.User">

    <!-- Mapping results when column names differ from field names -->
    <resultMap id="userResultMap" type="User">
        <id property="userId" column="id" />
        <result property="username" column="name" />
        <result property="age" column="age" />
        <result property="gender" column="gender" />
    </resultMap>

    <!-- Insert operation -->
    <insert id="saveUser" parameterType="User">
        INSERT INTO users (id, name, age, gender) 
        VALUES (#{userId}, #{username}, #{age}, #{gender})
    </insert>

    <!-- Select single record by ID -->
    <select id="selectById" parameterType="int" resultType="User">
        SELECT id, name, age, gender FROM users 
        WHERE id = #{id}
    </select>

    <!-- Select all records -->
    <select id="selectAll" resultType="User">
        SELECT id, name, age, gender FROM users
    </select>

    <!-- Update operation -->
    <update id="modifyUser" parameterType="User">
        UPDATE users 
        SET name = #{username}, age = #{age}, gender = #{gender} 
        WHERE id = #{userId}
    </update>

    <!-- Delete operation -->
    <delete id="removeUser" parameterType="int">
        DELETE FROM users WHERE id = #{id}
    </delete>

</mapper>
This mapper must be registered in the main MyBatis configuration file (mybatis-config.xml).
<configuration>
    <typeAliases>
        <typeAlias type="com.example.mybatis.entity.User" alias="User"/>
    </typeAliases>

    <mappers>
        <mapper resource="com/example/mybatis/entity/UserMapper.xml"/>
    </mappers>
</configuration>

Data Access Object Implementation

The DAO layer manages the database sessions and transaction handling. Each method utilizes the SqlSession to execute the mapped statements.
package com.example.mybatis.dao;

import com.example.mybatis.entity.User;
import com.example.mybatis.util.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import java.util.List;

public class UserDao {

    public void save(User user) {
        SqlSession session = null;
        try {
            session = MyBatisUtil.getSqlSession();
            session.insert("com.example.mybatis.entity.User.saveUser", user);
            session.commit();
        } catch (Exception e) {
            if (session != null) session.rollback();
            e.printStackTrace();
        } finally {
            if (session != null) session.close();
        }
    }

    public User findById(int id) {
        SqlSession session = null;
        try {
            session = MyBatisUtil.getSqlSession();
            return session.selectOne("com.example.mybatis.entity.User.selectById", id);
        } finally {
            if (session != null) session.close();
        }
    }

    public List<User> findAll() {
        SqlSession session = null;
        try {
            session = MyBatisUtil.getSqlSession();
            return session.selectList("com.example.mybatis.entity.User.selectAll");
        } finally {
            if (session != null) session.close();
        }
    }

    public void update(User user) {
        SqlSession session = null;
        try {
            session = MyBatisUtil.getSqlSession();
            session.update("com.example.mybatis.entity.User.modifyUser", user);
            session.commit();
        } catch (Exception e) {
            if (session != null) session.rollback();
            e.printStackTrace();
        } finally {
            if (session != null) session.close();
        }
    }

    public void delete(int id) {
        SqlSession session = null;
        try {
            session = MyBatisUtil.getSqlSession();
            session.delete("com.example.mybatis.entity.User.removeUser", id);
            session.commit();
        } catch (Exception e) {
            if (session != null) session.rollback();
            e.printStackTrace();
        } finally {
            if (session != null) session.close();
        }
    }
}

Key Implementation Details

  • Namespace Uniqueness: The namespace attribute in the mapper file typically uses the fully qualified class name of the entity to avoid naming conflicts.
  • Result Mapping: The resultMap element is essential when database columns do not directly match Java field names. If they match, resultType can be used directly.
  • Parameter Handling: For single parameters like int or String, the placeholder #{value} can use any name, though matching the parameter name is recommended for clarity.
  • Statement Tags: While <insert>, <update>, and <delete> serve specific semantic purposes, MyBatis allows flexibility in their usage for modifying operations. However, <select> is strictly required for queries to ensure correct result set handling.

Tags: MyBatis java CRUD SQL Mapping Persistence

Posted on Fri, 18 Sep 2026 16:28:18 +0000 by sungpeng