← 返回首页

MyBatis框架详解

📂 java ⏱ 4 min 632 words

什么是MyBatis

MyBatis是一款优秀的持久层框架,支持自定义SQL、存储过程和高级映射。

快速入门

实体类

public class User {
    private Long id;
    private String name;
    private String email;
    private Integer age;

    public User() {}

    public User(String name, String email, Integer age) {
        this.name = name;
        this.email = email;
        this.age = age;
    }

    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
    public Integer getAge() { return age; }
    public void setAge(Integer age) { this.age = age; }
}

Mapper接口

import org.apache.ibatis.annotations.*;
import java.util.List;

@Mapper
public interface UserMapper {
    @Select("SELECT * FROM users WHERE id = #{id}")
    User findById(Long id);

    @Select("SELECT * FROM users")
    List<User> findAll();

    @Insert("INSERT INTO users (name, email, age) VALUES (#{name}, #{email}, #{age})")
    @Options(useGeneratedKeys = true, keyProperty = "id")
    int insert(User user);

    @Update("UPDATE users SET name = #{name}, email = #{email} WHERE id = #{id}")
    int update(User user);

    @Delete("DELETE FROM users WHERE id = #{id}")
    int deleteById(Long id);
}

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 id="UserResult" type="User">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="email" column="email"/>
        <result property="age" column="age"/>
    </resultMap>

    <select id="findById" parameterType="Long" resultMap="UserResult">
        SELECT * FROM users WHERE id = #{id}
    </select>

    <select id="findAll" resultMap="UserResult">
        SELECT * FROM users
    </select>

    <insert id="insert" parameterType="User" useGeneratedKeys="true" keyProperty="id">
        INSERT INTO users (name, email, age) VALUES (#{name}, #{email}, #{age})
    </insert>

    <update id="update" parameterType="User">
        UPDATE users SET name = #{name}, email = #{email} WHERE id = #{id}
    </update>

    <delete id="deleteById" parameterType="Long">
        DELETE FROM users WHERE id = #{id}
    </delete>
</mapper>

动态SQL

<mapper namespace="com.example.mapper.UserMapper">
    <select id="findByCondition" parameterType="User" resultMap="UserResult">
        SELECT * FROM users
        <where>
            <if test="name != null and name != ''">
                AND name LIKE CONCAT('%', #{name}, '%')
            </if>
            <if test="age != null">
                AND age = #{age}
            </if>
            <if test="email != null and email != ''">
                AND email = #{email}
            </if>
        </where>
    </select>

    <insert id="batchInsert" parameterType="list">
        INSERT INTO users (name, email, age) VALUES
        <foreach collection="list" item="user" separator=",">
            (#{user.name}, #{user.email}, #{user.age})
        </foreach>
    </insert>

    <select id="chooseFind" parameterType="User" resultMap="UserResult">
        SELECT * FROM users
        <where>
            <choose>
                <when test="name != null">
                    AND name = #{name}
                </when>
                <when test="age != null">
                    AND age = #{age}
                </when>
                <otherwise>
                    AND id > 0
                </otherwise>
            </choose>
        </where>
    </select>
</mapper>

多表关联

<resultMap id="UserWithOrders" type="User">
    <id property="id" column="user_id"/>
    <result property="name" column="user_name"/>
    <collection property="orders" ofType="Order">
        <id property="id" column="order_id"/>
        <result property="orderNo" column="order_no"/>
        <result property="amount" column="amount"/>
    </collection>
</resultMap>

<select id="findUserWithOrders" resultMap="UserWithOrders">
    SELECT u.id as user_id, u.name as user_name,
           o.id as order_id, o.order_no, o.amount
    FROM users u
    LEFT JOIN orders o ON u.id = o.user_id
    WHERE u.id = #{id}
</select>

分页查询

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;

@Mapper
public interface UserMapper {
    List<User> findAll();
}

@Service
public class UserService {
    private final UserMapper userMapper;

    public PageInfo<User> findPage(int pageNum, int pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        List<User> users = userMapper.findAll();
        return new PageInfo<>(users);
    }
}

插件

import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.*;

import java.sql.Connection;
import java.util.Properties;

@Intercepts({
    @Signature(type = StatementHandler.class, method = "prepare",
               args = {Connection.class, Integer.class})
})
public class SlowSqlPlugin implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        long start = System.currentTimeMillis();
        Object result = invocation.proceed();
        long elapsed = System.currentTimeMillis() - start;
        if (elapsed > 1000) {
            System.out.println("慢SQL: " + elapsed + "ms");
        }
        return result;
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {}
}

MyBatis配置

<?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>
    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

    <typeAliases>
        <package name="com.example.entity"/>
    </typeAliases>

    <plugins>
        <plugin interceptor="com.example.plugin.SlowSqlPlugin"/>
    </plugins>

    <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"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <package name="com.example.mapper"/>
    </mappers>
</configuration>

MyBatis最佳实践

  1. 使用注解简化简单SQL
  2. 复杂SQL使用XML映射文件
  3. 合理使用动态SQL避免空条件
  4. 使用分页插件实现分页
  5. 缓存查询结果提高性能

总结

MyBatis提供了灵活的SQL映射能力。掌握MyBatis的核心特性能帮助你高效地进行数据库操作。