Mybatis

发布于:2024-05-23 ⋅ 阅读:(87) ⋅ 点赞:(0)

执行方案出现如下情况,即有的数据没有被成功赋值:

解决方式:

通过给字段起别名
通过resultMap的方式手动定义字段和属性的映射

resultMap是Mybatis用于解决数据库列名与POJO属性名不匹配问题的强大工具,它可以在查询,插入,更新操作中灵活地重命名参数。

标签

sql标签:将需要复用的sql片段放进去
同时有很多个mapper接口可能会用到这一段sql,我们可以将其提取出来。
往往结合include标签,将sql的id引入进来

<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>

resultMap标签:
在上面只需要定义 字段名 和 属性名 不一样的映射,而一样的则不需要专门定义出来。

并且将来通过resultMap来指定id,而不是resultType

 <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

 parameterType:
用于指定参数类型,这里我们mapper接口的方法中,传入AddressBook的引用参数
返回值为AddressBook类型,不用写全类名
这里还涉及到动态sql,常用的where标签和if标签

<select id="list" parameterType="AddressBook" resultType="AddressBook">
    select * from address_book
    <where>
        <if test="userId != null">
            and user_id = #{userId}
        </if>
        <if test="phone != null">
            and phone = #{phone}
        </if>
        <if test="isDefault != null">
            and is_default = #{isDefault}
        </if>
    </where>
</select>

参数占位符

mybatis提供了两种参数占位符:
#{} :执行SQL时,会将 #{} 占位符替换为?,将来自动设置参数值。从上述例子可以看出使用#{} 底层使用的是 PreparedStatement 
${} :拼接SQL。底层使用的是statement,会存在SQL注入问题

SQL语句中特殊字段处理

< 和 > 在xml文件中有特殊含义,我们需要进行转义

动态SQL

if标签:条件判断
 test属性:逻辑表达式

where标签:
替换where关键字
会动态的去掉第一个条件前的 and
如果所有的参数没有值则不加where关键
注意:需要给每个条件前都加上 and 关键字。

 <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

 插入操作

在数据添加成功后,有时候需要获取插入数据库数据的主键
我们通过useGeneratedKeys打开主键自增,并且将主键的返回值封装到id属性
id为主键,我们在插入的时候直接跳过即可,不需要我们赋值

<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>

修改操作

set标签 :可以用于动态包含需要更新的列,忽略其它不更新的列。
当然,也会用到if标签和where标签

<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>
 </set>
    where id = #{id};
 </update>

删除操作

删除一行

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

删除多行

会涉及到foreach标签,因为删除多行,一般都是以集合或者数组的形式传过来,我们可以遍历去获取其中的值 

foreach标签:

用来迭代任何可迭代的对象(如数组,集合)。
collection 属性: mybatis会将数组参数,封装为一个Map集合。
默认:array = 数组 当然,通过@Param注解,这样map集合名称和接口中的参数名一致
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>
等价于
delete from tb_brand where id in (1,2,3);

 当mapper接口参数有多个的时候,考虑用@Param注解,增加可读性

User select(@Param("username") String username,@Param("password") String password);

原理:

我们在接口方法中定义多个参数,Mybatis 会将这些参数封装成 map 集合,其中value就是参数值,而key在没有使用 @Param注解时有以下命名规则:

以 arg开头 : 第一个参数就叫 arg0,第二个参数就叫 arg1,依次类推
以 param 开头 : 第一个参数就叫 param1,第二个参数就叫 param2,依次类推

这样的话可读性会非常差,建议使用@Param注解,Mybatis 会将 arg 开头的键名替换为对应注解的属性值。

Mybatis参数传递

这里涉及mapper接口参数是单个还是多个

多个参数:就是一次传了好几个参数,如上面代码

单个参数:一次传一个参数,这里的一个可以指一个集合、数组或者一个POJO对象
集合包括List、Collection、Map
实际代码中,List、Collection、Array最好是通过@Param注解指定key的名称,不然可读性不高

以上需要@Param注解指定key名称,因为当没有@Param注解时:

mybatis底层会自动将它们封装为map集合,然后会给一套默认的key,我们需要用它默认的key,如arg0这样的去获得我们真正的集合对象。如果我们用默认给的key,可读性不高

说了这么多,List、Collection、Array这种用的都比较少,一般都是直接传POJO对象,或者说传集合过来,然后我们进行批量删除或批量添加【通过foreach标签】。


而POJO、Map不需要通过@Param注解来指定

原因是:Map对象本身就是一个map,它就不会走mybatis底层的map封装;

而POJO对象,mybatis默认情况下会通过反射机制,按照POJO的属性名来与SQL中的占位符进行映射。所以如果POJO对象的属性名我们不需要去额外变动的话,就不需要@Param注解。
相反,如果我们需要去额外指定的话,我们可以通过@Param来指定名称
或者
使用resultMap来手动完成映射

下面是一条update语句,参数为POJO,即addresBook对象,我们不需要通过@Param去指定

void update(AddressBook addressBook);

<update id="update" parameterType="addressBook">
    update address_book
    <set>
        <if test="consignee != null">
            consignee = #{consignee},
        </if>
        <if test="sex != null">
            sex = #{sex},
        </if>
        <if test="phone != null">
            phone = #{phone},
        </if>
        <if test="detail != null">
            detail = #{detail},
        </if>
        <if test="label != null">
            label = #{label},
        </if>
        <if test="isDefault != null">
            is_default = #{isDefault},
        </if>
    </set>
    where id = #{id}
</update>