MyBatis

0

95

MyBatis

分类: 技术社区 后端

标签:

时间: 2025-12-17

链接直达 手机查看

MyBatis 全面解析

MyBatis 是一款优秀的持久层框架,它消除了几乎所有的 JDBC 代码和手动设置参数以及获取结果集的操作,支持定制化 SQL、存储过程以及高级映射,通过 XML 或注解的方式将 SQL 语句与 Java 代码解耦,是 Java 生态中主流的 ORM(对象关系映射)框架之一。

一、核心优势

  1. 灵活可控:相比 Hibernate 等全自动 ORM 框架,MyBatis 不强制封装 SQL,允许开发者手写 SQL,适配复杂业务场景(如多表联查、复杂条件筛选)。
  2. 低侵入性:基于接口编程,无需继承/实现特定类,与业务代码解耦。
  3. 简化 JDBC 操作:自动处理连接、参数绑定、结果集映射,减少重复的 try-catch 代码。
  4. 动态 SQL:支持 <if>、<where>、<foreach> 等标签,灵活拼接 SQL,避免硬编码。
  5. 缓存机制:内置一级缓存(SqlSession 级别)和二级缓存(Mapper 级别),提升查询性能。

二、核心组件

1. 核心接口/类

组件作用
SqlSessionFactory会话工厂,创建 SqlSession 的核心类(单例,通过配置初始化)
SqlSession会话对象,用于执行 SQL、获取 Mapper 接口、管理事务(线程不安全)
Mapper 接口自定义接口,方法与 XML/注解中的 SQL 绑定(MyBatis 动态生成实现类)
Configuration全局配置类,存储 MyBatis 所有配置信息(数据源、映射规则、插件等)
Executor执行器,SqlSession 的底层执行器,处理 SQL 执行逻辑(默认 SimpleExecutor)

2. 核心配置文件(mybatis-config.xml)

全局配置文件,定义 MyBatis 的核心规则,示例:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 环境配置:数据源、事务管理器 -->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/> <!-- 事务管理:JDBC/MANAGED -->
            <dataSource type="POOLED"> <!-- 数据源:POOLED/UNPOOLED/JNDI -->
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/test?useSSL=false"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <!-- 映射器:指定 Mapper XML/接口位置 -->
    <mappers>
        <mapper resource="com/example/mapper/UserMapper.xml"/>
        <!-- 或注解方式:<mapper class="com.example.mapper.UserMapper"/> -->
    </mappers>
</configuration>

三、基本使用步骤

步骤 1:引入依赖(Maven)

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.16</version> <!-- 最新稳定版 -->
</dependency>
<!-- MySQL 驱动(按需替换) -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.33</version>
    <scope>runtime</scope>
</dependency>

步骤 2:定义实体类

public class User {
    private Long id;
    private String username;
    private Integer age;
    // getter/setter/toString
}

步骤 3:定义 Mapper 接口

public interface UserMapper {
    // 根据ID查询用户
    User selectById(Long id);
    
    // 新增用户
    int insert(User user);
    
    // 更新用户
    int update(User user);
    
    // 删除用户
    int delete(Long id);
}

步骤 4:编写 Mapper XML 文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace 绑定对应的 Mapper 接口 -->
<mapper namespace="com.example.mapper.UserMapper">
    <!-- 结果集映射:字段名 -> 实体类属性名(字段与属性不一致时需配置) -->
    <resultMap id="UserResultMap" type="com.example.entity.User">
        <id column="id" property="id"/>
        <result column="username" property="username"/>
        <result column="age" property="age"/>
    </resultMap>

    <!-- 查询:id 对应接口方法名 -->
    <select id="selectById" resultMap="UserResultMap">
        SELECT id, username, age FROM user WHERE id = #{id}
    </select>

    <!-- 新增 -->
    <insert id="insert" useGeneratedKeys="true" keyProperty="id">
        INSERT INTO user (username, age) VALUES (#{username}, #{age})
    </insert>

    <!-- 更新 -->
    <update id="update">
        UPDATE user 
        SET username = #{username}, age = #{age} 
        WHERE id = #{id}
    </update>

    <!-- 删除 -->
    <delete id="delete">
        DELETE FROM user WHERE id = #{id}
    </delete>
</mapper>

步骤 5:获取 SqlSession 并执行操作

public class MyBatisDemo {
    public static void main(String[] args) throws IOException {
        // 1. 加载核心配置文件
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        
        // 2. 创建 SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        
        // 3. 打开 SqlSession(true 表示自动提交事务)
        try (SqlSession session = sqlSessionFactory.openSession(true)) {
            // 4. 获取 Mapper 代理对象
            UserMapper userMapper = session.getMapper(UserMapper.class);
            
            // 5. 执行 CRUD
            User user = userMapper.selectById(1L);
            System.out.println(user);
            
            // 新增示例
            User newUser = new User();
            newUser.setUsername("test");
            newUser.setAge(20);
            userMapper.insert(newUser);
        }
    }
}

四、核心特性详解

1. 动态 SQL

通过标签动态拼接 SQL,解决硬编码问题,示例:

<select id="selectByCondition" resultMap="UserResultMap">
    SELECT id, username, age FROM user
    <where>
        <if test="username != null and username != ''">
            AND username LIKE CONCAT('%', #{username}, '%')
        </if>
        <if test="age != null">
            AND age = #{age}
        </if>
    </where>
</select>

常用动态标签:<if>、<where>、<set>、<foreach>、<choose/when/otherwise>。

2. 参数传递

  • 单个参数:直接用 #{参数名}(MyBatis 自动识别,参数名可任意)。
  • 多个参数:

    • 方式 1:使用 @Param 注解命名参数

      User selectByUsernameAndAge(@Param("username") String username, @Param("age") Integer age);
    • 方式 2:封装为实体类/Map。
  • 集合参数:通过 <foreach> 遍历

    <select id="selectByIds" resultMap="UserResultMap">
        SELECT id, username, age FROM user WHERE id IN
        <foreach collection="ids" item="id" open="(" separator="," close=")">
            #{id}
        </foreach>
    </select>

3. 结果映射

  • 简单映射:字段名与属性名一致时,直接用 resultType。
  • 复杂映射:

    • 一对一:<association>(如用户关联订单)。
    • 一对多:<collection>(如用户关联多个订单)。
      示例(一对多):

      <resultMap id="UserWithOrdersResultMap" type="User">
        <id column="user_id" property="id"/>
        <result column="username" property="username"/>
        <collection property="orders" ofType="Order">
            <id column="order_id" property="id"/>
            <result column="order_name" property="name"/>
        </collection>
      </resultMap>

4. 缓存

  • 一级缓存:默认开启,SqlSession 级别,同一 SqlSession 内多次查询相同 SQL 会缓存结果,关闭/提交 SqlSession 后失效。
  • 二级缓存:Mapper 级别,需手动开启:

    1. 全局配置:<setting name="cacheEnabled" value="true"/>。
    2. Mapper XML 中添加 <cache/>。
    3. 实体类实现 Serializable。

5. 注解开发

简单 SQL 可直接用注解替代 XML,示例:

public interface UserMapper {
    @Select("SELECT id, username, age FROM user WHERE id = #{id}")
    User selectById(Long id);
    
    @Insert("INSERT INTO user (username, age) VALUES (#{username}, #{age})")
    @Options(useGeneratedKeys = true, keyProperty = "id")
    int insert(User user);
}

注意:复杂 SQL(如动态 SQL、多表联查)建议用 XML 方式,更易维护。

五、MyBatis 进阶

1. 插件(Interceptor)

可拦截 MyBatis 核心方法(如执行器、参数处理器),实现分页、日志、权限控制等,示例(分页插件 PageHelper):

<plugins>
    <plugin interceptor="com.github.pagehelper.PageInterceptor">
        <property name="helperDialect" value="mysql"/>
    </plugin>
</plugins>

2. 集成 Spring/Spring Boot

实际开发中,MyBatis 通常与 Spring/Spring Boot 集成,核心依赖:

<!-- Spring Boot 整合 MyBatis -->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>3.0.3</version>
</dependency>

通过 application.yml 配置替代 XML,简化开发:

mybatis:
  mapper-locations: classpath:mapper/*.xml  # Mapper XML 位置
  type-aliases-package: com.example.entity  # 实体类别名包
  configuration:
    map-underscore-to-camel-case: true  # 自动下划线转驼峰
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/test?useSSL=false
    username: root
    password: 123456

3. 分页查询

除了 PageHelper,也可手动实现分页:

<select id="selectPage" resultMap="UserResultMap">
    SELECT id, username, age FROM user
    LIMIT #{offset}, #{size}
</select>

六、常见问题与最佳实践

  1. SQL 注入风险:使用 #{}(预编译)而非 ${}(字符串拼接),${} 仅用于表名/列名等动态场景。
  2. 性能优化:

    • 关闭不必要的二级缓存。
    • 合理使用 fetchSize、timeout 配置。
    • 避免 N+1 查询(用 <association>/<collection> 关联查询)。
  3. 字段与属性映射:开启 map-underscore-to-camel-case 自动下划线转驼峰,减少手动映射。
  4. 事务管理:Spring 环境下使用 @Transactional 注解管理事务,避免手动提交。

七、总结

MyBatis 以“灵活”为核心,兼顾 SQL 可控性和开发效率,是中大型 Java 项目中持久层的首选框架之一。掌握其核心配置、动态 SQL、结果映射等特性,结合 Spring Boot 集成,可高效实现数据库操作。

本文作者: Dylan Li

原文链接: MyBatis

免责声明: 文中如涉及第三方资源,均来自互联网,仅供学习研究,禁止商业使用,如有侵权,联系我们24小时内删除!

安全声明: 鉴于网络服务的特殊性,本站难以保证所收录网址的正确性或可靠性,请仔细识别你所访问的网站,注意您的个人隐私和财产安全。

评论0

😊 😃 😄 😁 😆 😅 😂 🤣 🙂 🙃 😉 😇 😏 😌 😍 😘 😗 😙 😚 😋 😛 😜 😝 😒 😔 😖 😞 😟 😠 😡 😳 😨 😰 😥 😢 😭 😱 😲 😵 😷 🤒 🤕 🤢 😴 🤤 😪 😫 😬 😮 🤲 🤜 🤛 🤚 🤝 🙏 🤞 🤟 🤘 🤙 👌 👍 👎 ✊ 👊 👏 🙌 👐 💪

暂时没有评论

数 据 加 载 中 ...