MyBatis基础

Mybatis是一款优秀的持久层框架,用于简化JDBC开发

在这里插入图片描述

使用Mybatis查询user表中所有数据

  1. 创建user表,添加数据
  2. 创建模块,导入坐标
  3. 编写MyBatis核心配置文件(mybatis-config.xml)—> 替换链接信息 解决硬编码问题
  4. 编写SQL映射文件(userMapper.xml)—> 统一管理sql语句,解决编码问题
  5. 编码:定义POJO类(User.java
    加载核心配置文件,获取SqlSessionFactory对象(MyBatisDemo.java
    获取SqlSession对象,执行SQL语句
    释放资源

在这里插入图片描述

Mapper代理开发

  1. 定义与SQL映射文件同名的Mapper接口,并且将Mapper接口和SQL映射文件放置在同一目录下
  2. 设置SQL映射文件的namespace属性为Mapper接口全限定名
  3. 在Mapper接口种定义方法,方法名就是SQL映射文件中的SQL语句的id,并保持参数类型和返回值类型一致
  4. 编码:
    通过SqlSession的getMapper方法获取Mapper接口的代理对象
    调用对应方法完成sql的排序

在这里插入图片描述
在这里插入图片描述

条件查询

数据库表的字段名称和实体类的属性名称不一样,则不能自动封装数据:

  1. 起别名:对不一样的列名起别名,让别名和实体类的属性名一样
    缺点:每一次查询都要定义一次别名
    使用sql片段起别名
    缺点:不灵活

    <!--sql片段-->
        <sql id="goods_colum">
            id, title as name, price
        </sql>
    
        <select id="selectAllGooods" resultType="Goods">
            select
                <include refid="goods_colum" />
            from tb_goods;
        </select>
    
  2. resultMap:
    1.定义标签
    2.在标签中,使用resultMap属性替换 resultType属性

    	<!--
            resultMap:
            id ;唯一的标识
            type:映射的类型,支持别名
         -->
    
        <resultMap id="goodsResultMap" type="goods">
            <!--
                id:完成主键字段的映射
                    colum:表的列名
                    property:实体类的属性名
                result:完成一般字段的映射
                    colum:表的列名
                    property:实体类的属性名
            -->
            <result column="title" property="name"></result>
        </resultMap>
    
        <select id="selectAllGooods" resultMap="goodsResultMap">
            select *
            from tb_goods;
        </select>
    

参数占位符:

  1. #{}:预编译,会将其替换为?,为了防止SQl注入
  2. ${}:字符串替换,拼接sql,会存在SQL注入问题
  3. 使用时机:
    *参数传递的时候:#{}
    *表名或者列名不固定的情况下:${}会存在SQL注入的问题

传入参数类型parameterType:可以省略

特殊字符处理:

  1. 转义字符:小于号尖括号左端(<)在xml中会去寻找右括号(>)所以不会单独存在会产生错误(&lt;)

        <select id="selectById" parameterType="int" resultMap="goodsResultMap">
            select *
            from tb_goods
            where id &lt; #{id};
        </select>
    
  2. CDATA区:当作纯文本处理

        <select id="selectById" parameterType="int" resultMap="goodsResultMap">
            select *
            from tb_goods
            where id
             <![CDATA[
             <
             ]]>
             #{id};
        </select>
    

多条件查询:
参数接收:

  1. 散装参数:如果方法中有多个参数,需要使用@Param(“SQL参数占位符名称”)
List<Goods> selectByCondition(@Param("price1")double prise, @Param("name")String title);
  1. 对象参数:对象的属性名称要和参数占位符一致,只需要保证SQL中的参数名和实体类属性名对应上
List<Goods> selectByCondition(Goods goods);//将参数封装
  1. map集合参数:只需要保证SQL中的参数名和map集合的键名的名称对应上
List<Goods> selectByCondition(Map map);

动态查询

  1. if语句:

    	<select id="selectByCondition" resultMap="goodsResultMap">
            select *
            from tb_goods
            where
            <if test="price1 > 0 and price1 != null">
                price &lt; #{price1}
            </if>
            <if test="price2 >= price1 and price2 > 0 and price2 != null">
                and price > #{price2}
            </if>
            <if test="name != null and name != ''">
                and title like #{name};
            </if>
        </select>
    

    test:逻辑表达式
    问题第一个参数不能为空
    在这里插入图片描述
    会出现错误,解决:

    1. 1=1恒等式:
    	<select id="selectByCondition" resultMap="goodsResultMap">
            select *
            from tb_goods
            where 1=1 
            <if test="price1 > 0 and price1 != null">
                and price &lt; #{price1}
            </if>
            <if test="price2 >= price1 and price2 > 0 and price2 != null">
                and price > #{price2}
            </if>
            <if test="name != null and name != ''">
                and title like #{name};
            </if>
        </select>
    
    1. 替换 where 关键字
        <select id="selectByCondition" resultMap="goodsResultMap">
            select *
            from tb_goods
            <where>
                <if test="price1 > 0 and price1 != null">
                    and price &lt; #{price1}
                </if>
                <if test="price2 >= price1 and price2 > 0 and price2 != null">
                    and price > #{price2}
                </if>
                <if test="name != null and name != ''">
                    and title like #{name};
                </if>
            </where>
        </select>
    
  2. choose(单条件的动态查询)

    	<select id="selectByConditionSingle" resultMap="goodsResultMap">
            select *
            from tb_goods
            # where <!--无参数参数传入时会报错,使用<where>解决-->
            <where>
                <choose><!--相当于switch-->
                    <when test="price > 0 and price != null">
                        price &lt; #{price}
                    </when><!--case-->
                    <when test="name != null and name != ''">
                        title like #{name}
                    </when>
                </choose>
            </where>
        </select>
    

    多个条件传入也只有第一个会使用到,使用可避免无参数传入时出现异常

添加

    <insert id="add">
        insert into tb_goods(title, price)
        value (#{name},#{price});
    </insert>

步骤:

  1. 编写接口方法:Mapper接口void add(Goods good);
  • 参数:除了id之外的所有数据
  • 结果:void
  1. 编写SQL语句:SQL映射文件
    (代码如上)
  2. 执行方法,测试
  • MyBatis事务:
  • openSession():默认开启事务,进行增删改操作后需要使用sqlSession.commit();手动提交事务
  • openSession(true):可以设置为自动提交事务(关闭事务)

返回添加数据的主键:

    <insert id="add" useGeneratedKeys="true" keyProperty="id">
        insert into tb_goods(title, price)
            value (#{name}, #{price});
    </insert>

修改

修改全部字段

  1. 编写接口方法:Mapper方法
  • 参数:所有数据

  • 结果:int

    void update(Goods good);
    
  1. 编写SQL语句:SQL映射文件

        <update id="updateAllById">
            update tb_goods
            set title = #{name},
                price = #{price}
            where id = #{id};
        </update>
    
  2. 执行方法,测试

修改动态字段

    <update id="updateAllById">
        update tb_goods
        <set>
            <if test="name != null and name != ''">
                title = #{name},
            </if>
            <if test="price != null and price != 0">
                price = #{price}
            </if>
        </set>
        where id = #{id};
    </update>

删除

删除一个

	<delete id="deleteById">
        delete
        from tb_goods
        where id = #{id};
    </delete>

步骤:

  1. 编写接口方法:Mapper接口
  • 参数:id
  • 结果:void
  1. 编写SQL语句:SQL映射文件
  2. 执行方法,测试

批量删除

int deleteAnyId(@Param("ids")int[] ids);//如果没有Param那么GoodsMapper.xml中就必须collection="array"
	<delete id="deleteAnyId">
        delete
        from tb_goods
        where id in
        (
        <foreach collection="ids" separator="," item="id">
            #{id}
        </foreach>
        );
    </delete>
    <delete id="deleteAnyId">
        delete
        from tb_goods
        where id in
        <foreach collection="ids" separator="," item="id" open="(" close=")">
            #{id}
        </foreach>
        ;
    </delete>

必须使用item不然会有异常

步骤:

  1. 编写接口方法:Mapper接口
  • 参数:id数组
  • 结果:void
  1. 编写SQL语句:SQL映射文件
  • mybatis会将数组参数,封装为一个Map集合:
  • 默认:array = 数组
  • 使用@Param注解会改变map集合默认的key名称
  1. 执行方法,测试

MyBatis参数传递

MyBatis接口方法中可以接收各种各样的参数,MyBatis底层对这些参数进行不同的封装处理方式

  • 单个参数:(使用@Param(“SQL语句参数占位符一致”)注解的形式,不使用默认)
  1. POJO类型:直接使用,属性名 和 参数占位符名称一致
  2. Map集合:直接使用,键名 和 参数占位符一致
  3. Collection:封装成Map集合
    map.put(“arg0”,collection集合);
    map.put(“collection”,collection集合);
  4. List:封装成Map集合
    map.put(“arg0”,list集合);
    map.put(“collection”,list集合);
    map.put(“list”,list集合);
  5. Array:封装成Map集合
    map.put(“arg0”,数组);
    map.put(“array”,数组);
  6. 其他类型:直接使用
  • 多个参数:
    map.put(“arg0”,参数值1);
    map.put(“param1”,参数值1);
    map.add(“param2”,参数值2);
    map.add(“arg1”,参数值2);

使用Param是替用arg命名
map.put(“username”,参数值1);
map.put(“param1”,参数值1);
map.add(“param2”,参数值2);
map.add(“password”,参数值2);

使用ParamNameResolver类来进行参数封装,
@Param(“SQL语句参数占位符一致”)

使用注解完成增删改查

在这里插入图片描述

面试题

面试题三:#{}和${}的区别是什么?

${}是字符串替换,#{}是预处理;

Mybatis在处理 时,就是把 {}时,就是把 时,就是把{}直接替换成变量的值。而Mybatis在处理#{}时,会对sql语句进行预处理,将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;

使用#{}可以有效的防止SQL注入,提高系统安全性。

面试题四:Mybatis的Xml映射文件中,不同的Xml映射文件,id是否可以重复?

不同的Xml映射文件,如果配置了namespace,那么id可以重复;如果没有配置namespace,那么id不能重复;

原因就是namespace+id是作为Map的key使用的,如果没有namespace,就剩下id,那么,id重复会导致数据互相覆盖。有了namespace,自然id就可以重复,namespace不同,namespace+id自然也就不同。

备注:在旧版本的Mybatis中,namespace是可选的,不过新版本的namespace已经是必须的了。

面试题:【2022最新版】MyBatis面试题总结(38道题含答案解析)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值