执行方案出现如下情况,即有的数据没有被成功赋值:
解决方式:
通过给字段起别名
通过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>