Mybatis常用功能

吴书松
吴书松
发布于 2025-05-06 / 8 阅读
0

Mybatis常用功能

mybatis功能

1、插入数据之后,返回主键给实体类


<insert id="insertUser" parameterType="SysUser" useGeneratedKeys="true" keyProperty="userId">
</insert>
关键参数:
parameterType="SysUser" : 请求参数类型
useGeneratedKeys="true" :开启主键返回
keyProperty="userId":返回到对应的字段里面

2、配置逻辑删除字段,自动拼接

3、MetaObjectHandler 元数据处理

对mybaits的insert和update操作的元数据做默认值的处理 https://blog.csdn.net/wddblog/article/details/136466632 实现该handler,重写接口

注意,实体类上需要添加注解: fill = FieldFill.INSERT

@TableField(fill = FieldFill.INSERT,value = "create_time")
 @Override
public void insertFill(MetaObject metaObject) {
    log.debug("mybatis plus start insert fill ....");
    LocalDateTime now = LocalDateTime.now();

    fillValIfNullByName("createTime", now, metaObject, true);
    fillValIfNullByName("updateTime", now, metaObject, true);
    fillValIfNullByName("createBy", getUserName(), metaObject, true);
    fillValIfNullByName("updateBy", getUserName(), metaObject, true);

    // 删除标记自动填充
    fillValIfNullByName("delFlag", CommonConstants.STATUS_NORMAL, metaObject, true);
}

@Override
public void updateFill(MetaObject metaObject) {
    log.debug("mybatis plus start update fill ....");
    fillValIfNullByName("updateTime", LocalDateTime.now(), metaObject, true);
    fillValIfNullByName("updateBy", getUserName(), metaObject, true);
}

/**
 * 填充值,先判断是否有手动设置,优先手动设置的值,例如:job必须手动设置
 * @param fieldName 属性名
 * @param fieldVal 属性值
 * @param metaObject MetaObject
 * @param isCover 是否覆盖原有值,避免更新操作手动入参
 */
private static void fillValIfNullByName(String fieldName, Object fieldVal, MetaObject metaObject, boolean isCover) {
    // 0. 如果填充值为空
    if (fieldVal == null) {
       return;
    }

    // 1. 没有 set 方法
    if (!metaObject.hasSetter(fieldName)) {
       return;
    }
    // 2. 如果用户有手动设置的值
    Object userSetValue = metaObject.getValue(fieldName);
    String setValueStr = StrUtil.str(userSetValue, Charset.defaultCharset());
    if (StrUtil.isNotBlank(setValueStr) && !isCover) {
       return;
    }
    // 3. field 类型相同时设置
    Class<?> getterType = metaObject.getGetterType(fieldName);
    if (ClassUtils.isAssignableValue(getterType, fieldVal)) {
       metaObject.setValue(fieldName, fieldVal);
    }
}

Mybatis基本用法

1. 使用 实现批量操作

是 MyBatis 中一个非常强大的元素,它允许你遍历集合并对每个元素执行 SQL 语句的一部分。这在批量插入、更新或删除操作中尤其有用。

示例代码:批量插入用户信息

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

// Mapper接口
int batchInsertUsers(List<User> users);

2. 实现动态 SQL

元素用于根据条件包含部分 SQL 语句。这在构建动态查询时非常有用,特别是当查询条件不是固定的时候。

示例代码:根据用户ID和用户名查询用户

<select id="selectUsersByCondition" parameterType="map" resultType="User">
    SELECT * FROM users
    WHERE 1=1
    <if test=" query.id != null ">
        AND id = #{query.id}
    </if>
    <if test=" query.name != null and query.name != '' ">
        AND name LIKE CONCAT('%', #{name}, '%')
    </if>
    <if test=" query.roleIds != null and query.roleIds.size() > 0 ">
        ..........
    </if>
</select>


// Mapper接口
List<User> selectUsersByCondition(@Param(value = "query")User query);

3. 、、 实现多条件分支查询

choose标签是按顺序判断其内部when标签中的test条件出否成立,如果有一个成立,则 choose 结束。当 choose 中所有 when 的条件都不满则时,则执行 otherwise 中的sql。类似于Java 的 switch 语句,choose 为 switch,when 为 case,otherwise 则为 default。

示例代码:根据用户ID或用户名查询用户

<select id="selectUserByChoose" parameterType="map" resultType="User">
    SELECT * FROM users
    <where>
        <choose>
            <when test="query.id != null">
                id = #{query.id}
            </when>
            <when test="query.name != null and query.name != ''">
                name LIKE CONCAT('%', #{query.name}, '%')
            </when>
            <otherwise>
                1=1 <!-- 总是为真,相当于无条件 -->
            </otherwise>
        </choose>
    </where>
</select>


// Mapper接口
List<User> selectUserByChoose(@Param(value = "query")User query);

4. 优化 SQL 语句

元素可以用来去除 SQL 语句中不需要的部分,比如多余的 AND、OR 或者前缀。

示例代码:更新用户信息,去除多余的逗号和 AND

<update id="updateUser" parameterType="User">
    UPDATE users
    <trim prefix="SET" suffixOverrides=",">
        <if test="user.name != null">name = #{user.name},</if>
        <if test="user.age != null">age = #{user.age},</if>
    </trim>
    WHERE id = #{id}
</update>


// Mapper接口
int updateUser(@Param(value = "user")User user);

5. 使用 获取自动生成的主键

在插入记录时,经常需要获取数据库自动生成的主键值。 元素可以在插入操作后执行一个查询来获取这个值。

示例代码:插入用户并获取自动生成的主键

<insert id="insertUserAndGetId" parameterType="User" useGeneratedKeys="true" keyProperty="id">
    <!-- 这里 useGeneratedKeys="true" 和 keyProperty="id" 也可以不使用 selectKey,取决于数据库和 MyBatis 配置 -->
    <selectKey keyProperty="id" resultType="int" order="AFTER">
        SELECT LAST_INSERT_ID()
    </selectKey>
    INSERT INTO users (name, age) VALUES (#{user.name}, #{user.age})
</insert>


// Mapper接口
int insertUserAndGetId(@Param(value = "user")User user);

注意:对于支持自动生成主键的数据库(如 MySQL 的 AUTO_INCREMENT),通常不需要 ,因为 MyBatis 可以自动捕获这些值。

6. 使用 Mapper 接口和注解

除了 XML 配置外,MyBatis 还支持使用 Mapper 接口和注解来简化开发。

示例代码:使用 @Select 注解查询用户

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

7. 关联查询

MyBatis 支持多种关联查询方式,包括嵌套查询和延迟加载。

示例代码:使用嵌套查询查询用户及其订单

<!-- 查询用户 -->
<select id="selectUserWithOrders" resultMap="userOrderResultMap">
    SELECT * FROM users WHERE id = #{id}
</select>


<resultMap id="userOrderResultMap" type="User">
    <id property="id" column="id" />
    <result property="name" column="name" />
    <collection property="orders" ofType="Order"
                select="selectOrdersByUserId" column="id"/>
</resultMap>


<!-- 根据用户ID查询订单 -->
<select id="selectOrdersByUserId" resultType="Order">
    SELECT * FROM orders WHERE user_id = #{userId}
</select>

8. 延迟加载

延迟加载是一种优化技术,它允许在真正需要关联数据时再去加载这些数据,从而减少数据库的访问次数。

配置:在 MyBatis 配置文件中启用延迟加载

<settings>
    <setting name="lazyLoadingEnabled" value="true"/>
    <setting name="aggressiveLazyLoading" value="false"/>
</settings>

9. 分页查询

MyBatis 本身不直接支持分页查询,但可以通过 SQL 的 LIMIT 语句或结合插件来实现。

示例代码:使用 LIMIT 实现分页

<select id="selectUsersByPage" parameterType="map" resultType="User">
    SELECT * FROM users
    LIMIT #{offset}, #{limit}
</select>


// Mapper接口
List<User> selectUsersByPage(Map<String, Object> params);

10. 使用 MyBatis-Plus 简化开发

MyBatis-Plus 是 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

示例:使用 MyBatis-Plus 的 Service 层进行分页查询

@Autowired
private IUserService userService;

public Page<User> selectUserPage(int pageNum, int pageSize) {
    Page<User> page = new Page<>(pageNum, pageSize);
    return userService.page(page, null); // null 表示不添加任何查询条件
}

mybatis常用配置

# mybaits-plus配置
mybatis-plus:
  #mapper-locations: classpath:/mapper/*/*Mapper.xml,classpath:/mapper/*Mapper.xml,classpath*:mapper/**/*Mapper.xml,classpath*:mapper/*Mapper.xml
  mapper-locations: classpath:/mapper/*/*Mapper.xml,classpath:/mapper/*Mapper.xml
  type-handlers-package: com.jxjumeng.common.mybatis.handler
  global-config:
    banner: false
    db-config:
      id-type: auto
      table-underline: true
      logic-delete-value: 1
      logic-not-delete-value: 0
  configuration:
    map-underscore-to-camel-case: true
    shrink-whitespaces-in-sql: true
    # log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 控制台日志打印
    log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl # 日志输出到logback中