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中