Flyinsky's Codes
879 字
4 分钟
持久层框架Mybatis

一、概述#

MyBatis 是一个优秀的持久层框架,它基于 SQL 映射的思想,通过 XML 或注解方式将 SQL 语句与 Java 对象关联起来。与 Hibernate 等全自动 ORM 框架相比,MyBatis 提供了对 SQL 操作的更多控制,适合复杂 SQL 查询和性能优化场景。

特点:

  1. 支持直接编写 SQL。
  2. 动态 SQL 提供了灵活的 SQL 拼接方式。
  3. 简化了 JDBC 操作,避免了繁琐的 ResultSet 和 Statement 处理。
  4. 提供一级缓存和二级缓存机制。

二、环境配置#

1. 引入依赖#

在 Maven 项目中引入 MyBatis 相关依赖:

<dependencies>
    <!-- MyBatis 核心 -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.13</version>
    </dependency>
    <!-- MyBatis-Log4j 日志支持 -->
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.20.0</version>
    </dependency>
    <!-- MySQL 驱动 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.33</version>
    </dependency>
</dependencies>
2. 配置数据库连接#

创建 mybatis-config.xml 配置文件:

<?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>
    <!-- 数据库环境配置 -->
    <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/testdb?useSSL=false&amp;serverTimezone=UTC"/>
                <property name="username" value="root"/>
                <property name="password" value="password"/>
            </dataSource>
        </environment>
    </environments>
    <!-- 全局设置 -->
    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/> <!-- 驼峰命名映射 -->
        <setting name="logImpl" value="LOG4J"/> <!-- 日志实现 -->
    </settings>
</configuration>
3. Mapper XML 文件配置#

UserMapper.xml 为例:

<?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.mapper.UserMapper">
    <!-- 查询所有用户 -->
    <select id="findAll" resultType="com.example.entity.User">
        SELECT id, username, email FROM user
    </select>
</mapper>

三、开发步骤#

1. 数据库表结构#

假设有以下两张表:

  • user:用户表

    CREATE TABLE user (
        id INT AUTO_INCREMENT PRIMARY KEY,
        username VARCHAR(50) NOT NULL,
        email VARCHAR(100),
        role_id INT
    );
  • role:角色表

    CREATE TABLE role (
        id INT AUTO_INCREMENT PRIMARY KEY,
        role_name VARCHAR(50) NOT NULL
    );
2. 配置 mybatis-config.xml#
<configuration>
    <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/testdb?useSSL=false&amp;serverTimezone=UTC"/>
                <property name="username" value="root"/>
                <property name="password" value="password"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="com/example/mapper/UserMapper.xml"/>
        <mapper resource="com/example/mapper/RoleMapper.xml"/>
    </mappers>
</configuration>

四、Mapper 配置#

1. 实体类定义#
User 实体类#
package com.example.entity;

public class User {
    private Integer id;
    private String username;
    private String email;
    private Role role; // 对应的角色对象

    // Getters and Setters
}
Role 实体类#
package com.example.entity;

public class Role {
    private Integer id;
    private String roleName;

    // Getters and Setters
}

2. UserMapper.xml 定义#
增删改查接口#
<?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.mapper.UserMapper">

    <!-- resultMap 定义 -->
    <resultMap id="UserResultMap" type="com.example.entity.User">
        <id property="id" column="id"/>
        <result property="username" column="username"/>
        <result property="email" column="email"/>
        <association property="role" javaType="com.example.entity.Role">
            <id property="id" column="role_id"/>
            <result property="roleName" column="role_name"/>
        </association>
    </resultMap>

    <!-- 查询所有用户 -->
    <select id="findAll" resultMap="UserResultMap">
        SELECT u.id, u.username, u.email, r.id AS role_id, r.role_name
        FROM user u
        LEFT JOIN role r ON u.role_id = r.id
    </select>

    <!-- 动态查询 -->
    <select id="findByCondition" resultMap="UserResultMap">
        SELECT u.id, u.username, u.email, r.id AS role_id, r.role_name
        FROM user u
        LEFT JOIN role r ON u.role_id = r.id
        <where>
            <if test="username != null and username != ''">
                AND u.username = #{username}
            </if>
            <if test="email != null and email != ''">
                AND u.email = #{email}
            </if>
        </where>
    </select>

    <!-- 插入用户 -->
    <insert id="insertUser" parameterType="com.example.entity.User">
        INSERT INTO user (username, email, role_id)
        VALUES (#{username}, #{email}, #{role.id})
    </insert>

    <!-- 更新用户 -->
    <update id="updateUser" parameterType="com.example.entity.User">
        UPDATE user
        SET username = #{username},
            email = #{email},
            role_id = #{role.id}
        WHERE id = #{id}
    </update>

    <!-- 删除用户 -->
    <delete id="deleteUser" parameterType="int">
        DELETE FROM user WHERE id = #{id}
    </delete>

</mapper>
3. RoleMapper.xml 定义#
<?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.mapper.RoleMapper">

    <!-- 查询所有角色 -->
    <select id="findAll" resultType="com.example.entity.Role">
        SELECT id, role_name FROM role
    </select>

</mapper>

五、代码实现#

1. Mapper 接口#
package com.example.mapper;

import com.example.entity.User;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface UserMapper {
    List<User> findAll();
    List<User> findByCondition(@Param("username") String username, @Param("email") String email);
    void insertUser(User user);
    void updateUser(User user);
    void deleteUser(int id);
}

2. 测试代码#
package com.example;

import com.example.entity.User;
import com.example.entity.Role;
import com.example.mapper.UserMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.Reader;
import java.util.List;

public class MyBatisTest {
    public static void main(String[] args) {
        try (Reader reader = Resources.getResourceAsReader("mybatis-config.xml")) {
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
            try (SqlSession sqlSession = sqlSessionFactory.openSession(true)) {
                UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

                // 查询所有用户
                List<User> users = userMapper.findAll();
                users.forEach(user -> System.out.println(user.getUsername() + " - " + user.getRole().getRoleName()));

                // 插入用户
                Role role = new Role();
                role.setId(1); // 假设角色 ID 为 1
                User newUser = new User();
                newUser.setUsername("John");
                newUser.setEmail("john@example.com");
                newUser.setRole(role);
                userMapper.insertUser(newUser);

                // 更新用户
                newUser.setEmail("updated@example.com");
                userMapper.updateUser(newUser);

                // 按条件查询
                List<User> filteredUsers = userMapper.findByCondition("John", null);
                filteredUsers.forEach(user -> System.out.println(user.getUsername()));

                // 删除用户
                userMapper.deleteUser(newUser.getId());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}