【MyBatis】一天之内快速掌握MyBatis的增删改查

5 篇文章 0 订阅
4 篇文章 0 订阅

MyBatis

文章介绍:

一共不到8000字,一天之内可以快速学会mybatis的增删改查,
以及经常使用的操作,不讲废话,只将眼光聚焦到实操上,也可以搭配黑马的视频观看
看完之后,可以自己找个mybatis源码课继续学习
,但是一般的业务代码也只用到文章大部分内容

Mybatis是一款半ORM的持久层框架,简化JDBC的框架

一、快速入门


  1. 创建SQL表
  2. 编写MyBatis配置文件
  3. 编写SQL语句
  4. java定义POJO类
  5. SqlSessionFactory对象,获取SqlSession
  6. 执行Sql语句
  7. 释放资源

二、mapper代理开发


MyBtais使用mapper代理开发三个步骤:

  1. 定义mapper接口方法
  2. 定义SQL语句,其实就是写mapper.xml
  3. 调用者生成mapper 实例化对象,来进行操作
  • 主要记得mapper接口要和resources目录下的mapper.xml一个目录;

  • 如果Mapper接口名称和SQL映射文件名称相同,并在同一目录下,则可以使用包扫描的方式简化SQL映射文件的加载。也就是将核心配置文件的加载映射配置文件的配置修改为

<mappers>
    <!--加载sql映射文件-->
    <!-- <mapper resource="com/itheima/mapper/UserMapper.xml"/>-->
    <!--Mapper代理方式-->
    <package name="com.it.mapper"/>
</mappers>
  • 重复性高的sql语句,在mapper.xml中,使用sql标签,定义sql片段。

三、难点业务


难点1:遇到数据库表字段与实体类属性名名称不一致,如何处理


1. SQL字段起别名

使用sql标签定义statement片段,将数据库字段as成实体类属性名。在statement中include进来。
例如

<sql id="brand_column">
	id, brand_name as brandName, company_name as companyName, ordered, description, status
</sql>
<select id="selectAll" resultType="brand">
    select
    <include refid="brand_column" />
    from tb_brand;
</select>
2. ResultMap 封装结果集,实现数据库字段和实体类属性的映射关系

实现多字段数据库表只有些许字段需要对应修改,完成不一致的属性名和列名的映射

例如

<resultMap id="brandResultMap" type="brand">
     <!--
            id:完成主键字段的映射
                column:表的列名
                property:实体类的属性名
            result:完成一般字段的映射
                column:表的列名
                property:实体类的属性名
        -->
     <result column="brand_name" property="brandName"/>
     <result column="company_name" property="companyName"/>
</resultMap>

<select id="selectAll" resultMap="brandResultMap">
    select *
    from tb_brand;
</select>

难点2: where条件如何添加参数


1. sql语句参数占位符使用
  1. #{}:推荐使用,在sql语句中是 ?存在,就是jdbc的PreparedStatement
  2. ${}:拼接sql语句,存在sql注入问题,底层就是Statement
  3. 使用时机:参数传递用#{};对于可变列名、表名用${},但是实际中没什么用
2.parameterType使用

parameterType,对于有参数的mapper接口,一般在xml中可以省略,框架会自动封装。
例子

/*
* id:唯一标识符
* parameterType:传递参数类型
* resultMap:返回类型
*/
<select id="selectById" parameterType="int" resultMap="brandResultMap">
    select *
    from tb_brand where id = ${id};
</select>
3.SQL语句中特殊字段处理
  1. 使用xml的转义字符:例如&lt; 就是 < 的转义字符。
  2. <![CDATA[内容]]>,内容里面就写有歧义的内容
4. 总结例子
/*
* id:唯一标识符
* parameterType:传递参数类型,可以省略
* resultMap:返回类型
*/
<select id="selectById" parameterType="int" resultMap="brandResultMap">
    select *
    from tb_brand where id 
    <![CDATA[
    		<
    ]]>
     #{id};
</select>

难点3: 多条件查询


1. 重点:
条件需要模糊查询
2. mapper接口参数接受
  1. 散装参数接受

    使用 @Param("参数名称") 注解标记每一个参数,在映射配置文件中就需要使用 #{参数名称} 进行占位,两个名称要一致。
    代码:

List<Brand> selectByCondition(@Param("status") int status, @Param("companyName") String companyName,@Param("brandName") String brandName);

  1. 实体类封装参数
    保证SQL语句的占位参数名称#{参数名称}跟实体类属性名一致就行了
List<Brand> selectByCondition(Brand brand);
  1. map封装参数
    保证map集合的key跟sql的占位参数名称#{参数名称}一致就行了
List<Brand> selectByCondition(Map map);
3.sql语句编写
<select id="selectByCondition" resultMap="brandResultMap">
    select *
    from tb_brand
    where status = #{status}
    and company_name like #{companyName}
    and brand_name like #{brandName}
</select>

记得占位参数名称#{"参数名称"}与三种方式要对应上。

4.调用

在调用中,要实现模糊查询,应该在调用时封装参数

// 处理参数
    companyName = "%" + companyName + "%";
    brandName = "%" + brandName + "%";

难点4: 添加数据


1.接口方法

参数使用实体类对象

void add(Object obj);
2.sql语句

正常的insert语句

<insert id="add">
    insert into tb_brand (brand_name, company_name, ordered, description, status)
    values (#{brandName}, #{companyName}, #{ordered}, #{description}, #{status});
</insert>
3.提交事务
  1. SqlSession sqlSession = sqlSessionFactory.openSession(true); //设置自动提交事务,这种情况不需要手动提交事务了

  2. sqlSession.commit();//手动提交事务

4.主键返回
在业务中,可能需要主键注入到对象中,融合再读取作为其他的外键

所以,我们要修改mapper里面的代码

<insert id="add" useGeneratedKeys="true" keyProperty="id">
    insert into tb_brand (brand_name, company_name, ordered, description, status)
    values (#{brandName}, #{companyName}, #{ordered}, #{description}, #{status});
</insert>
新增的两个属性
  1. useGeneratedKeys:是够获取自动增长的主键值。true表示获取
  2. keyProperty :指定将获取到的主键值封装到实体类对象哪儿个属性里,比如写的是"id",就类似于写到brand.id

难点4: 删除单条数据

1.编写接口方法
在 Mapper 接口中定义根据id删除方法。
/**
  * 根据id删除
  */
void deleteById(int id);
2 编写SQL语句
在 Mapper.xml 映射配置文件中编写删除一行数据的 statement
<delete id="deleteById">
    delete from tb_brand where id = #{id};
</delete>

四、动态sql


1.动态多条件查询


1. 描述
在业务中,用户存在只填写一个信息,进行查询的情况,
需要我们动态去拼接statement
2.if标签
  • 使用if标签,实现条件判断,逻辑表达式写在test=" condition "里面。
  • 例子:
<select id="selectByCondition" resultMap="brandResultMap">
    select *
    from tb_brand
    where
        <if test="status != null">
            and status = #{status}
        </if>
        <if test="companyName != null and companyName != '' ">
            and company_name like #{companyName}
        </if>
        <if test="brandName != null and brandName != '' ">
            and brand_name like #{brandName}
        </if>
</select>
3. where 标签

在上小节内容中,还存在一个问题,如果status条件不通过,会导致sql语句存在语法问题,有两种方法解决这个逻辑运算符问题

  1. 使用恒等式 ,例如 条件中加入1=1,每个条件都用and连接
<select ...
    where 1=1
        <if test="status != null">
            and status = #{status}
     ....
</select>
  1. MyBatis中使用where标签能帮我们解决这个问题,会自动判断语句,在这个例子中,会自动帮我消去多余的and。
    例子
<select id="selectByCondition" resultMap="brandResultMap">
    select *
    from tb_brand
    <where>
        <if test="status != null">
            and status = #{status}
        </if>
        <if test="companyName != null and companyName != '' ">
            and company_name like #{companyName}
        </if>
        <if test="brandName != null and brandName != '' ">
            and brand_name like #{brandName}
        </if>
    </where>
</select>

2.动态单条件查询


1.编写mapper接口方法
由于是可选条件,所以采用传入对象方法
/**
  * 单条件动态查询
  * @param brand
  * @return
  */
List<Brand> selectByConditionSingle(Brand brand);
2. 编写sql方法
<select id="selectByConditionSingle" resultMap="brandResultMap">
    select *
    from tb_brand
    <where>
        <choose><!--相当于switch-->
            <when test="status != null"><!--相当于case-->
                status = #{status}
            </when>
            <when test="companyName != null and companyName != '' "><!--相当于case-->
                company_name like #{companyName}
            </when>
            <when test="brandName != null and brandName != ''"><!--相当于case-->
                brand_name like #{brandName}
            </when>
        </choose>
    </where>
</select>
当然没有where标签时候是下面这样
<select id="selectByConditionSingle" resultMap="brandResultMap">
    select *
    from tb_brand
    where
        <choose><!--相当于switch-->
            <when test="status != null"><!--相当于case-->
                status = #{status}
            </when>
            <when test="companyName != null and companyName != '' "><!--相当于case-->
                company_name like #{companyName}
            </when>
            <when test="brandName != null and brandName != ''"><!--相当于case-->
                brand_name like #{brandName}
            </when>
            <otherwise><!--相当于default-->
            	1=1
            </otherwise>
        </choose>
    where
</select>

3.动态update


1. 编写接口方法
 /**
   * 修改
   */
int update(Brand brand);
上述方法参数 Brand 就是封装了需要修改的数据,而id肯定是有数据的,
这也是和添加方法的区别,而且update会返回受影响行数
2.动态sql语句
<update id="update">
    update tb_brand
    <set>
        <if test="brandName != null and brandName != ''">
            brand_name = #{brandName},
        </if>
        <if test="companyName != null and companyName != ''">
            company_name = #{companyName},
        </if>
        <if test="ordered != null">
            ordered = #{ordered},
        </if>
        <if test="description != null and description != ''">
            description = #{description},
        </if>
        <if test="status != null">
            status = #{status}
        </if>
    </set>
    where id = #{id};
</update>
set标签的作用
  1. 解决逗号的问题
  2. 解决防止条件都不成立的问题

4.批量删除(使用动态SQL)


用到的sql:delete from table where id in (?,?,?);,其中的?是可变的

1.编写接口方法
在 Mapper 接口中定义删除多行数据的方法。
/**
  * 批量删除
  */
void deleteByIds(int[] ids);

/**
  * 使用@param注解,来重新定义map的key的名字
  */
void deleteByIds(@param("ids")int[] ids)

参数是一个数组,数组中存储的是多条数据的id

2.编写SQL语句
在 Mapper.xml 映射配置文件中编写删除多条数据的 statement。

编写SQL时需要遍历数组来拼接SQL语句。Mybatis 提供了 foreach 标签供我们使用
foreach 标签

用来迭代任何可迭代的对象(如数组,集合)。

  • collection 属性:
    1. mybatis会将数组参数,封装为一个Map集合。
    2. 默认:array = 数组
    3. 使用@Param注解改变map集合的默认key的名称,"自定义名称"取代"array"
  • item 属性:本次迭代获取到的元素。
  • separator 属性:集合项迭代之间的分隔符。foreach 标签不会错误地添加多余的分隔符。也就是最后一次迭代不会加分隔符。
  • open 属性:该属性值是在拼接SQL语句之前拼接的语句,只会拼接一次
  • close 属性:该属性值是在拼接SQL语句拼接后拼接的语句,只会拼接一次
<delete id="deleteByIds">
    delete from tb_brand where id
    in
    <foreach collection="array" item="id" separator="," open="(" close=")">
        #{id}
    </foreach>
    ;
</delete>

五、参数传递


总结以上,我们可以发现,接口方法编写的时候,为什么有的地方要加@param注解,有的地方不加,而且为什么加@param注解后,就可以使用其值,如果不加@param注解,能否表示占位参数呢?我们根据 MyBatis底层的类,可以总结以下规律

1.多个参数

Mybatis 会将这些参数封装成 Map 集合对象,值就是参数值,不加@param注解时,每个参数会加两个key,例如参数1,会加

map.put(“arg0”,参数值1);
map.put(“param1”,参数值1);

使用 @Param 注解后,Mybatis 会将 arg 开头的键名替换为对应注解的属性值。

add(@Param("name")String name,...)
map.put(“name”,参数值1);
map.put(“param1”,参数值1);

2.单个参数

  1. POJO 类型

    直接使用。要求 属性名 和 参数占位符名称 一致

  2. Map 集合类型

    直接使用。要求 map集合的键名 和 参数占位符名称 一致

  3. Collection 集合类型

    Mybatis 会将集合封装到 map 集合中,如下:

	map.put(“arg0”,collection集合);
	map.put(“collection”,collection集合;
可以使用 @Param 注解替换map集合中默认的 arg 键名。
  1. List 集合类型

    Mybatis 会将List集合封装到 map 集合中,如下:

map.put(“arg0”,list集合);
map.put(“collection”,list集合);
map.put(“list”,list集合);

可以使用 @Param 注解替换map集合中默认的 arg 键名。

  1. Array 类型

Mybatis 会将集合封装到 map 集合中,如下:

map.put(“arg0”,数组);
map.put(“array”,数组);
可以使用 @Param 注解替换map集合中默认的 arg 键名。
  1. 其他类型

    比如int类型,参数占位符名称 叫什么都可以。尽量做到见名知意

六、注解开发

查询 :@Select
添加 :@Insert
修改 :@Update
删除 :@Delete

注解完成简单功能,配置文件完成复杂功能。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值