Khái niệm và cách sử dụng MyBatis trong ứng dụng Java

Giới thiệu về MyBatis

MyBatis là một framework bền vững (persistent layer) hỗ trợ truy vấn SQL thông thường, xử lý stored procedure và ánh xạ nâng cao. Nó giúp loại bỏ hầu hết các đoạn mã JDBC thủ công như thiết lập tham số, truy xuất kết quả từ ResultSet. Với cấu trúc đơn giản dựa trên XML hoặc annotation, MyBatis cho phép ánh xạ trực tiếp giữa các interface Java và các bản ghi trong cơ sở dữ liệu.

Cấu trúc kiến trúc của MyBatis

MyBatis được tổ chức thành ba lớp chính: cấu hình hệ thống, quản lý session và ánh xạ câu truy vấn. Việc hiểu rõ cấu trúc này giúp tối ưu hóa hiệu suất và bảo trì code dễ dàng hơn.

Thiết lập môi trường với Maven

Đầu tiên, tạo một dự án Maven bình thường. Sau đó, thêm dependency MyBatis vào file pom.xml:

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.14</version>
</dependency>

File cấu hình chính: mybatis-config.xml

Tạo file cấu hình tại thư mục src/main/resources:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
  <typeAliases>
    <package name="com.example.pojo" />
  </typeAliases>

  <environments default="development">
    <environment id="development">
      <transactionManager type="JDBC" />
      <dataSource type="POOLED">
        <property name="driver" value="com.mysql.cj.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/mydb?serverTimezone=UTC" />
        <property name="username" value="root" />
        <property name="password" value="root" />
      </dataSource>
    </environment>
  </environments>

  <mappers>
    <mapper resource="mappers/UserMapper.xml" />
  </mappers>
</configuration>

Xử lý tài nguyên tĩnh trong Maven

Nếu gặp lỗi không tìm thấy file XML hoặc properties, cần cấu hình lại build để đảm bảo các file tĩnh được bao gồm:

<build>
  <resources>
    <resource>
      <directory>src/main/resources</directory>
      <includes>
        <include>**/*.xml</include>
        <include>**/*.properties</include>
      </includes>
    </resource>
    <resource>
      <directory>src/main/java</directory>
      <includes>
        <include>**/*.xml</include>
        <include>**/*.properties</include>
      </includes>
      <filtering>true</filtering>
    </resource>
  </resources>
</build>

Tạo SqlSessionFactory và SqlSession

Sử dụng class tiện ích để khởi tạo kết nối:

public class DatabaseUtil {
    private static SqlSessionFactory factory;

    static {
        try (InputStream config = Resources.getResourceAsStream("mybatis-config.xml")) {
            factory = new SqlSessionFactoryBuilder().build(config);
        } catch (IOException e) {
            throw new RuntimeException("Không thể khởi tạo SqlSessionFactory", e);
        }
    }

    public static SqlSession getSession() {
        return factory.openSession();
    }
}

Ánh xạ đối tượng - CSDL

Tạo entity:

public class User {
    private int id;
    private String name;
    private String password;

    // Getter, Setter, toString
}

Tạo interface mapper:

public interface UserMapper {
    List<User> getAllUsers();
}

Ánh xạ bằng XML

Tạo file UserMapper.xml trong package tương ứng:

<?xml version="1.0" encoding="UTF-8"?>
<mapper namespace="com.example.mapper.UserMapper">
  <select id="getAllUsers" resultType="com.example.pojo.User">
    SELECT * FROM users
  </select>
</mapper>

Hoặc dùng annotation

public interface UserMapper {
    @Select("SELECT * FROM users")
    List<User> getAllUsers();
}

Thử nghiệm truy vấn

@Test
public void testQuery() {
    try (SqlSession session = DatabaseUtil.getSession()) {
        UserMapper mapper = session.getMapper(UserMapper.class);
        List<User> users = mapper.getAllUsers();
        users.forEach(System.out::println);
    }
}

Chuyển đổi dữ liệu phức tạp với Map

Khi tham số hoặc kết quả không phải là đối tượng cụ thể, dùng Map để điều phối:

<insert id="insertUser" parameterType="map">
  INSERT INTO users (id, name, password)
  VALUES (#{userId}, #{userName}, #{userPwd})
</insert>

Trong test:

Map<String, Object> params = new HashMap<>();
params.put("userId", 100);
params.put("userName", "test");
params.put("userPwd", "123");

try (SqlSession session = DatabaseUtil.getSession()) {
    UserMapper mapper = session.getMapper(UserMapper.class);
    mapper.insertUser(params);
    session.commit();
}

Ánh xạ quan hệ nhiều-một (One-to-One)

Với bảng liên kết giữa sinh viên và giáo viên:

<select id="getStudentWithTeacher" resultMap="studentWithTeacher">
  SELECT s.id sid, s.name sname, t.name tname
  FROM student s JOIN teacher t ON s.tid = t.id
</select>

<resultMap id="studentWithTeacher" type="Student">
  <result property="id" column="sid" />
  <result property="name" column="sname" />
  <association property="teacher" javaType="Teacher">
    <result property="name" column="tname" />
  </association>
</resultMap>

Phân trang với LIMIT

SQL hỗ trợ phân trang bằng lệnh LIMIT:

SELECT * FROM users LIMIT #{offset}, #{size}

Interface:

List<User> paginateUsers(Map<String, Integer> params);

Test:

Map<String, Integer> params = new HashMap<>();
params.put("offset", (currentPage - 1) * pageSize);
params.put("size", pageSize);

List<User> users = mapper.paginateUsers(params);

Tích hợp với các công nghệ khác

MyBatis có hỗ trợ tích hợp mạnh mẽ với Spring, Hibernate, JPA và nhiều công nghệ backend khác, giúp xây dựng hệ thống lớn một cách linh hoạt.

Thẻ: mybatis Java sql orm Maven

Đăng vào ngày 12 tháng 9 lúc 18:05