1、#{}和¥{}的区别
#{}是预编译处理(参数占位符),¥{}是字符串替换
Mybatis在处理#{}时,会将sql中的#{}替换为?,调用PreparedStatement的set方法来赋值
Mybatis在处理¥{},就是把¥{}替换为变量的值
#{}可以防止sql注入
一般能用#的就别用$
$方式一般用于传入数据库对象,例如传入表名.
2、当实体类属性和表字段不一时,如何配置
问题同:如何封装结果集
(1)在查询的sql语句中定义字段的别名,让字段别名与实体类属性名一致
(2)通过<resultMap>
来映射字段名和实体类属性名
<mapper namespace="com.rewind.test01.mapper.TestMapper">
<resultMap id="subjects" type="com.rewind.test01.entity.EduSubject">
<result column="id" property="id"></result>
<result column="title" property="title"></result>
<result column="parent_id" property="parentId"></result>
<result column="sort" property="sort"></result>
<result column="gmt_create" property="gmtCreate"></result>
<result column="gmt_modified" property="gmtModified"></result>
</resultMap>
<select id="findAll" resultMap="subjects">
select * from edu_subject
</select>
</mapper>
3、模糊查询like
(1)在java代码中添加sql通配符
//java代码
String name = "%小刚";
//xml配置
<select id="findName">
select * from users where name like #{name}
</select>
(2)在sql语句中拼接通配符,会引起sql注入
<select id="findName">
select * from users where name like "%"#{name}
</select>
4、Mapper(Dao)接口的工作原理
Mapper接口没有实现类,当调用接口方法时,接口全限定名+方法名拼接字符串作为key值,可唯一定位一个MapperStatement。在Mybatis中,每一个<select><insert><update><delete>
标签都会被解析为一个MapperStatement对象。
5、Dao接口方法参数不同,能重载吗?
不能,因为是使用全限定名+方法名
的保存寻找策略。
6、如何分页
(1)sql语句,limit 开始索引,每页查询条数
(2)Mybatis使用RowBounds对象进行分页
原理:逻辑分页会将所有的结果都查询到,然后根据RowBounds中提供的offset和limit值来获取最后的结果。
//Service
List<EduSubject> list = testMapper.findAll(new RowBounds(1,5));
//mapper,xml无需配置分页
List<EduSubject> findAll(RowBounds rowBounds);
(3)分页插件
原理:使用Mybatis提供的接口,实现自定义插件,在插件的拦截方法内拦截执行的sql,然后重写sql,根据方言,添加对应的物理分页语句与物理分页参数。
7、执行批量插入
<insert id="insertBatch" >
insert into person ( <include refid="Base_Column_List" /> )
values
<foreach collection="list" item="item" index="index" separator=",">
(null,#{item.name},#{item.sex},#{item.address})
</foreach>
</insert>
参数解释:
foreach 的主要作用在构建 in 条件中,它可以在 sql 语句中进行迭代一个集合。foreach 元素的属性主要有 collection,item,separator,index,open,close。
- collection:指定要遍历的集合。表示传入过来的参数的数据类型。该属性是必须指定的,要做 foreach 的对象。在使用 foreach 的时候最关键的也是最容易出错的就是 collection 属性。在不同情况 下,该属性的值是不一样的,主要有一下 3 种情况:
a. 如果传入的是单参数且参数类型是一个 List 的时候,collection 属性值为 list。
b. 如果传入的是单参数且参数类型是一个数组的时候,collection 的属性值为 array。
c. 如果传入的参数是多个的时候,就需要把它们封装成 Map,当然单参数也可以封装成 Map。Map 对象没有默认的键。 - item:表示集合中每一个元素进行迭代时的别名。将当前遍历出的元素赋值给指定的变量,然后用#{变量名},就能取出变量的值,也就是当前遍历出的元素。
- separator:表示在每次进行迭代之间以什么符号作为分隔符。
select * from tab where id in(1,2,3)
相当于1,2,3之间的”,” - index:索引。index 指定一个名字,用于表示在迭代过程中,每次迭代到的位置。遍历 list 的时候 index 就是索引,遍历 map 的时候 index 表示的就是 map 的 key,item 就是 map 的值。
- open/close:表示该语句以什么开始/结束。
8、在Mapper中如何传递多个参数
(1)dao层函数
select * from edu_subject where name=#{0} and age=#{1}
在xml中,#{n}
代表接收的第n个参数
(2)使用@param
注解
//mapper
EduSubject findOne(@Param("title") String abc);
//xml
<select id="findOne" resultType="com.rewind.test01.entity.EduSubject">
select * from edu_subject where title=#{title}
</select>
(3)将参数集封装为map
//java
Map<String,Object> map = new HashMap();
map.put("myid",5);
map.put("myname","张三");
map.put("mypwd","????");
int result = userMapper.addUser(map);
//xml,#{myid},#{myname},#{mypwd}为map的键
<insert id="addUser2" parameterType="Map">
insert into mybatis.user(id, name, pwd) values (#{myid},#{myname},#{mypwd});
</insert>
9、不同的xml文件,id可否重复
不同的xml文件,如果配置了namespace,那么id可以重复,否则不可以;
10、parameterType可以省略吗?
如果 是基本类型,或者是java自身的引用类型,在mybatis 运行时,会自动的进行匹配,可以省略parameterType属性。
如果是你自己声明的一个类型,因为可能在引入的jar包中有同名的类,所以你需要制定,这个时候的类型是什么。