首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【SSM-Mybatis(二)】java持久层框架-Mybatis!本文重点对mybatis的映射文件进行了分析!涵盖if、foreach、choose、sql片段抽取、多表查询、注解开发等内容!

【SSM-Mybatis(二)】java持久层框架-Mybatis!本文重点对mybatis的映射文件进行了分析!涵盖if、foreach、choose、sql片段抽取、多表查询、注解开发等内容!

作者头像
用户11865655
发布2025-10-13 17:24:22
发布2025-10-13 17:24:22
10600
代码可运行
举报
文章被收录于专栏:CSDN专栏CSDN专栏
运行总次数:0
代码可运行

动态sql语句

概述

Mybatis的映射文件中,前面我们的SQL都是比较简单的,有些时候业务逻辑复杂时,我们的SQL是动态变化的,此时在前面的学习中我们的SQL就不能满足要求了

参考的官方文档,描述如下:

MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其他类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句有多么痛苦。拼接的时候要确保不能忘了必要的空格,还要注意省掉列名列表最后的逗号。利用动态 SQL 这一特性可以彻底摆脱这种痛苦。 通常使用动态 SQL 不可能是独立的一部分,MyBatis 当然使用一种强大的动态 SQL 语言来改进这种情形,这种语言可以被用在任意的 SQL 映射语句中。 动态 SQL 元素和使用 JSTL 或其他类似基于 XML 的文本处理器相似。在 MyBatis 之前的版本中,有很多的元素需要来了解。MyBatis 3 大大提升了它们,现在用不到原先一半的元素就可以了。MyBatis 采用功能强大的基于 OGNL 的表达式来消除其他元素。

  • if
  • choose (when, otherwise)
  • trim (where, set)
  • foreach
if (动态标签)
  • 根据实体类的不同取值,使用不同的SQL语句来进行查询。
    • 比如在id如果不为空时可以根据id查询,如果username不同时还要加入用户名作为条件。
    • 这种情况在多条件组合拆线呢中经常会碰到
代码语言:javascript
代码运行次数:0
运行
复制
<select id="findAll" resultType="user" parameterType="user">
    select *
    from person
    <where>
        <if test="id!=0">
            id=#{id}
        </if>
        <if test="name!=null">
            and name=#{name}
        </if>
        <if test="sex!=0">
            and sex=#{sex};
        </if>
    </where>
</select>
  • <if>判断传入的参数是否符合判断,如果符合则执行标签内的sql语句
foreach(动态标签)
  • 循环执行sql的拼接操作
代码语言:javascript
代码运行次数:0
运行
复制
<select id="findByIds" resultType="user" parameterType="user">
        select *
        from person
        <where>
            <foreach collection="list" open="id in(" close=")" item="id" separator=",">
                #{id}
            </foreach>
        </where>
    </select>
  • <foreach>标签属性含义:
    • collection:接收的数据类型
    • open:拼接的开头字符串
    • close:拼接的结尾字符串
    • item:遍历循环中的结果值
    • separator:拼接字符串中的分隔符
SQL片段抽取
  • SQL中可将重复的sql语句提取出来,使用时用include引用即可,最终达到sql语句重用的目的
代码语言:javascript
代码运行次数:0
运行
复制
<sql id="selectPerson">select * from person</sql>

<select id="findAll" resultType="user">
    <include refid="selectPerson"></include>
</select>
choose(动态标签)
  • choose标签的结构其实和java中的switch循环和if else if判断的结构体非常相似
    • 倒不如说,choose标签就是一个switch

typeHandlers标签

  • 无论mybatis标签在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时,都会用类型处理器将获取的值以合适的方式转换乘java类型。
  • 下表描述了一些默认的类型处理器(截取部分) 类型处理器java类型jdbc类型BooleanTypeHandlerjava.lang.Boolean,boolean数据库兼容的BooleanByteTypeHandlerjava.lang.Byte,byte数据库兼容的numeric或byteShorTypeHandlerjava.lang.Short,short数据库兼容的numeric或short integerIntegerTypeHandlerjava.lang.Integer,int数据库兼容的numeric或IntegerLongTypeHandlerjava.lang.Long,long数据库兼容的numeric或Long Integer
  • 你可以重写类型处理器或创建你自己的类型处理器来处理不支持的或非标准的类型。
    • 具体做法为:实现org.apache.ibatis.type.TypeHandler接口,或继承一个很便利的类 org.apache.ibatis.type.BaseTypeHander,如何可以选择性地将它映射到一个JDBC类型。
    • 例如需求:一个java中的Date数据类型,我想将值存到数据库的时候存成一个1970至今的毫秒数,取出来时转换乘java的Date,即java的Date与数据库的varchar毫秒值之间转换
开发步骤
  1. 定义转换类继承类BaseTypeHandler< T >
  2. 覆盖4个未实现的方法,其中setNonNullParameter为java程序设置数据到数据库的回调方法,getNullableResult为查询时,mysql的字符串类型转换成java的Type类型的方法
  3. 在Mybatis核心配置文件中进行注册
  4. 测试转换是否正确
代码语言:javascript
代码运行次数:0
运行
复制
public class DateTypeHandler extends BaseTypeHandler<Date> {
 
    // 实现java类型转换成数据库类型
    @Override
    public void setNonNullParameter(PreparedStatement preparedStatement, int i, Date date, JdbcType jdbcType) throws SQLException {
        long time = date.getTime();
        preparedStatement.setLong(i,time);
    }

    // 从数据库类型转换成java类型
    @Override
    public Date getNullableResult(ResultSet resultSet, String s) throws SQLException {
        long aLong = resultSet.getLong(s);
        Date date = new Date(aLong);
        return date;
    }

    // 从数据库类型转换成java类型
    @Override
    public Date getNullableResult(ResultSet resultSet, int i) throws SQLException {
        long aLong = resultSet.getLong(i);
        Date date = new Date(aLong);
        return date;
    }

    // 从数据库类型转换成java类型
    @Override
    public Date getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
        long aLong = callableStatement.getLong(i);
        Date date = new Date(aLong);
        return date;
    }
}

plugins标签

MyBatis 可以使用第三方的插件来对功能进行扩展,分页助手PageHelper是将分页的复杂操作进行封装,使用简单的方式即可获得分页的相关数据

开发步骤:
  1. 导入通用PageHelper的坐标
  2. 在mybatis核心配置文件中配置PageHelper插件
  3. 测试分页数据获取

多表查询

一对一配置:
  • 使用<resultMap>配置
代码语言:javascript
代码运行次数:0
运行
复制
<resultMap id="studentMap" type="student">
    <!--
            column 代表为sql语句查询出来的列名
            property 代表为实体类中的属性名
            两者关系为 一个查询出来的属性 一个接收查询出来的属性
        -->
    <id property="studentId" column="sid"></id>
    <result column="studentName" property="studentName"></result>
    <result column="sexId" property="sexId"></result>

    <!-- 实体类内部的属性 -->
    <!--        <result column="teacherId" property="teacher.teacherId"></result>-->
    <!--        <result column="teacherName" property="teacher.teacherName"></result>-->

    <!--
            property :实体类中声明的属性名称(private Teacher teacher)
            javaType :实体类中声明的属性类型(Teacher)
        -->
    <association property="teacher" javaType="teacher">
        <id column="teacherId" property="teacherId"></id>
        <result column="teacherName" property="teacherName"></result>
    </association>

</resultMap>

<select id="queryAll" resultMap="studentMap">
        select *,s.studentId sid from student s,teacher t WHERE s.teacherId = t.teacherId
</select>
一对多配置:
  • 使用<resultMap>+<collection>做配置
代码语言:javascript
代码运行次数:0
运行
复制
<resultMap id="teacherMap" type="teacher">
    <id column="teacherId" property="teacherId"></id>
    <result column="teacherName" property="teacherName"></result>

    <!-- collection使用与association大体一致 -->
    <collection property="studentList" ofType="student">
        <id property="studentId" column="sid"></id>
        <result column="studentName" property="studentName"></result>
        <result column="sexId" property="sexId"></result>
    </collection>

</resultMap>

<select id="queryOneForNum" resultMap="teacherMap">
    SELECT * FROM student s,teacher t WHERE s.teacherId = t.teacherId
</select>
多对多配置:
  • 使用<resultMap>+<collection>做配置
  • 多对多与一对多,在配置文件中是相差无异的,它更改的最多的还是sql语句,而不是resultMap

注解开发

常用注解

近年来,注解开发越来越流行,Mybatis也可以使用注解开发方法,这样我们就可以减少编写Mapper映射文件了。

常用注解列表:

注解名

功能

@Insert

实现新增

@Update

实现更新

@Delete

实现删除

@Select

实现查询

@Result

实现结果集封装

@Results

可以与@Result一起使用,封装多个结果集

@One

实现一对一结果集封装

@Many

实现一对多结果集封装

使用注解开发时需要配置mappers

代码语言:javascript
代码运行次数:0
运行
复制
<mappers>
    <!-- 指定接口所在的包 -->
    <package name="com.demonode.mapper"/>
</mappers>

扫描接口所在包后,直接在接口上使用注解进行开发

代码语言:javascript
代码运行次数:0
运行
复制
@Mapper
public interface PersonMapper {
    @Select("select * from person")
    public List<Person> findAll();

    @Select("select * from person where id = #{id}")
    public Person findOne(int id);

    @Insert("insert into person values(null ,#{name},#{sex},null)")
    public void addPerson(Person person);

    @Update("update person set name=#{name},sex=#{sex} where id=#{id}")
    public void updatePerson(Person person);

    @Delete("delete from person where id=#{id}")
    public void delPerson(int id);
}
Mybatis的注解实现复杂映射开发
  • 实现复杂关系映射之前,我们可以在映射文件中通过配置<resultMap>来实现,使用注解后,我们可以是以哦那个@Results注解,@Result注解,@One注解,@Many注解组合完成复杂关系的配置

注解

说明

@Results

代替的是标签该注解中可以使用单个@Result注解,也可以使用@Result集合。使用格式:@Results({@Result(),@Result()}) 或 @Results(@Result())

@Result

代替了标签和标签。

@Result中的属性介绍:
  • column:数据库的列名
  • property:需要装配的属性名
  • one:需要使用@One的注解(@Result(one=@One)())
  • many:需要使用的@Many注解(@Result(many=@many)())
一对一
  • 第一种:不同的**【外表】**使用另外的类来调用属性字段
代码语言:javascript
代码运行次数:0
运行
复制
@Select(
    "select *,s.studentId sid from student s,teacher t WHERE s.teacherId = t.teacherId"
)
@Results({
    @Result(column = "sid",property = "studentId"),
    @Result(column = "studentName",property = "studentName"),
    @Result(column = "sexId",property = "sexId"),
    @Result(column = "teacherId",property = "teacher.teacherId"),
    @Result(column = "teacherName",property = "teacher.teacherName"),
})
public List<student> findAll();
  • 第二种:不同的**【外表】**使用@Result内部的参数来调用其他方法获得数据
代码语言:javascript
代码运行次数:0
运行
复制
@Select("select * from student")
@Results({
@Result(column = "sid",property = "studentId"),
@Result(column = "studentName",property = "studentName"),
@Result(column = "sexId",property = "sexId"),
@Result(
property = "teacher",// 实例对象(属性名称)
column = "teacherId",// 查询数据的 列
javaType = teacher.class,// 接收的类型
one = @One(select = "com.demonode.mapper.StudentMapper.findOne")// 调用的方法

)
})
public List<student> findAll();
一对多 或 多对多
  • 与一对多几乎无异,只是将@One换成@Many
代码语言:javascript
代码运行次数:0
运行
复制
@Select("select * from teacher")
@Results({
    @Result(column = "teacherId",property = "teacherId"),
    @Result(column = "teacherName",property = "teacherName"),
    @Result(
        property = "studentList",// 实例对象(属性名称)
        column = "teacherId",// 查询数据的 列
        javaType = List.class,// 接收的类型
        many = @Many(
            select = "com.demonode.mapper.StudentMapper.findOneTeacher"
        )// 调用的方法
    )
})
public List<teacher> findTeacherAndStudent();
  • 多对多只是多了个中间表,实际也相差无几
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-05-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 动态sql语句
    • 概述
    • if (动态标签)
    • foreach(动态标签)
    • SQL片段抽取
    • choose(动态标签)
  • typeHandlers标签
    • 开发步骤
  • plugins标签
    • 开发步骤:
  • 多表查询
    • 一对一配置:
    • 一对多配置:
    • 多对多配置:
  • 注解开发
    • 常用注解
    • Mybatis的注解实现复杂映射开发
      • @Result中的属性介绍:
      • 一对一
      • 一对多 或 多对多
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档