目录
一. 实体类与数据库表属性名称不一致
在初始开发学习中,我们经常要求数据库表的字段名称和实体类对应属性的名称必须相同,原因就是这样便于底层的结果封装,但是当我们在实际开发中如果实体类和数据库不一致,就会产生结果全为null的情况,原因就是由于对应字段不一致所以没有将属性封装进去,这时我们就需要人为地指明映射关系。
1. 赋别名
方法一是使用mysql语句 as ,给属性赋别名(与实体类同名)。
<!--方法一:使用mysql语句 as ,给属性赋别名(与实体类同名)-->
<select id="findAll" resultType="com.sdust.pojo.User">
select userid as uid,username as uname,password as pwd from user
</select>
2. 全局配置
方法二是使用resultMap从全局配置,给属性赋别名(与实体类同名)。
<!--方法二:使用resultMap从全局配置,给属性赋别名(与实体类同名)-->
<!--
1.主属性就用id标签;其他的属性就用result标签
2.property:实体类中的属性 ; column:数据库表中的字段
-->
<resultMap id="userMap" type="com.sdust.pojo.User">
<id property="uid" column="userid"/>
<result property="uname" column="username"/>
<result property="pwd" column="password"/>
</resultMap>
<!--注意resultType改为resultMap来映射对应关系-->
<select id="findAll" resultMap="userMap">
select * from user
</select>
二. 传参方式的注意事项
1. # 传参和 $ 传参的区别
(1)#传参:预编译处理,类似于之前学习jdbc时候的 ?占位符,提交的字符只会被当作当前sql语句的参数处理,不会改变原sql语句的含义,会在实际传入的值前后加引号
(2)$传参: 直接传参,参数会被直接拼接到sql语句中,不会在实际传入的值前后加引号,会改变原sql语句的含义引发sql注入问题
# select * from tb_student order by "stu_age";
$ select * from tb_student order by stu_age;
传参方式总结: 能用 # 用# ,用不了#用$
<!--
mybatis传参的两种方式:
#传参:预编译处理,类似于之前学习jdbc时候的 ?占位符,提交的字符只会被当作当前sql语句的参数处理,不会改变原sql语句的含义,会在实际传入的值前后加引号
$传参: 直接传参,参数会被直接拼接到sql语句中,不会在实际传入的值前后加引号,会改变原sql语句的含义引发sql注入问题
# select * from tb_student order by "stu_age";
$ select * from tb_student order by stu_age;
传参方式总结: 能用 # 用# ,用不了#用$
-->
<!--#{}内可以任意字符串取参数,只表示占位符-->
<select id="findUserByUserName" resultMap="userMap" parameterType="String">
select * from user where username = #{uname}
</select>
<!--只能${value}或者${_parameter}取参数-->
<select id="findAllOrderBy" parameterType="java.lang.String" resultMap="userMap">
select * from user order by ${value};
</select>
2. 单参数传递
(1)基本数据类型
在传递单个基本类型的参数时#{}取参数的命名可以任意,他只表示一个占位符;而${}取参数只能使用:
- ${value}或者${_parameter} 进行固定取参
- 使用 @Param() 注解进行指定映射取参
public List<User> findAllOrderBy(@Param("orderBy") String orderBy);
<select id="findAllOrderBy" parameterType="java.lang.String" resultMap="userMap">
select * from user order by ${orderBy};
</select>
(2)对象类型
传递单个对象类型参数时,#{}和${}内都可以填写对象的相应属性名直接取参。但如果使用@Param()注解,则{}都必须使用 注解映射名.属性名 的形式进行取参。
public User findUserByUserName(@Param("newuser") User uname);
public List<User> findAllOrderBy(@Param("orderBy") User orderBy);
<select id="findUserByUserName" resultMap="userMap" parameterType="com.sdust.pojo.User">
select * from user where username = #{newuser.uname}
</select>
<select id="findAllOrderBy" parameterType="com.sdust.pojo.User" resultMap="userMap">
select * from user order by ${orderBy.uname};
</select>
3. 多参数传递
(1)使用下标传参
#{}里面的数字代表你传入参数的顺序。由于是多参数那么就不能使用parameterType, 改用#{index}是第几个就用第几个的索引,索引从0开始。
public List<XXXBean> getXXXBeanList(String xxId, String xxCode);
<select id="getXXXBeanList" resultType="XXBean">
select t.* from tableName where id = #{0} and name = #{1}
</select>
(2)使用Param注解传参
以前在<select>语句中要带parameterType的,现在可以不要这样写。
public AddrInfo getAddrInfo(@Param("corpId")int corpId, @Param("addrId")int addrId);
<select id="getAddrInfo" resultMap="com.xxx.xxx.AddrInfo">
SELECT * FROM addr__info
where addr_id=#{addrId} and corp_id=#{corpId}
</select>
三. package以及typeAliases配置
1. <typeAliases> 配置
使用typeAliases配置别名,它只能配置实体类的别名,这样mapper.xml文件中就不用再写全限定类名了
2. <package>配置
用于指定要配置别名的包,当指定之后,该包下的实体类都会注册别名,并且类名就是别名,不再区分大小写。
<!--使用typeAliases配置别名,它只能配置实体类的别名,这样mapper.xml文件中就不用再写全限定类名了 -->
<typeAliases>
<!--typeAlias用于配置别名。type属性指定的是实体类全限定类名。alias属性指定别名,当指定了别名就再区分大小写
<typeAlias type="com.itheima.domain.User" alias="user"></typeAlias>-->
<!-- 用于指定要配置别名的包,当指定之后,该包下的实体类都会注册别名,并且类名就是别名,不再区分大小写-->
<package name="com.sdust.pojo"></package>
</typeAliases>
四. mapper.xml文件的扫描方式
1. 在注册映射文件时使用<package name="包名">标签进行包扫描时,需要映射文件全限定名和接口全限定名一样(包名+文件名相同),不然会报错。
<!-- 配置映射文件的位置 -->
<mappers>
<package name="com.sdust.dao"></package>
</mappers>
2. 在注册映射文件时使用<mapper class="">标签进行注解开发时,需要映射文件全限定名和接口全限定名一样(包名+文件名相同),不然会报错。
3. 在注册映射文件时使用<mapper resource=""/>标签进行配置开发时,不需要映射文件名和接口名一样,只需能指明配置文件位置即可。
<mappers>
<mapper resource="mapper/UserMapper.xml"></mapper>
</mappers>