配置接口绑定
核心文件的配置
<mappers>
<!--<mapper resource="top.byfree.mapper.UserMapper"/>-->
<package name="top.byfree.mapper"/>
</mappers>
由于我们会在mapper包下创建java接口类,所以之前的/可以替换为.了,使用mapper标签配置,由于我们会有很多接口类,所以mapper标签会有很多
可以是用pakage标签将mapper包引入即可
mapper XML 配置
<mapper namespace="top.byfree.mapper.UserMapper">
</mapper>
mapper标签的命名空间namespace必须是全限定路径,用以找到定义的接口文件。
接口文件的定义
public interface UserMapper {
/**
* 查询所有用户信息
* @return
*/
List<User> selAll();
}
首先接口名要和mapper XML文件名一致,然后抽象方法名称和xml文件中的标签里面的id属性值对应,才可以正常使用
使用流程
SqlSession session = MyBatisUtil.getSession();
UserMapper mapper = session.getMapper(UserMapper.class);
List<user> list = mapper.selAll();
for (User u : list) {
System.out.println(u);
}
session.close();
还是先使用工具类获取session对象
session下使用getMapper方法,传入要获取的接口的class对象
调用mapper接口内的方法的到返回值即可
接口绑定和@Param注解解决多参数问题
问题:使用mybatis时候没办法传入多个参数
之前拥有多个参数的操作我们是使用一个实体类或者是map集合封装解决问题的。但是这种方式实际上还是传了一个参数。
现在有了接口绑定后我们就可以真正实现多参数的绑定了
解决
1. 在接口里的抽象方法中写多个参数
User selByName(String name, String password);
2. 在mapper XML文件里面使用这些参数
<select id="selByName" resultType="user">
select * from user where name=#{0} and password=#{1}
</select>
3. 执行这个方法
SqlSession session = MyBatisUtil.getSession();
UserMapper mapper = session.getMapper(UserMapper.class);
User user = mapper.selByName2("jelly", "123");
System.out.println(user);
session.close();
出现问题
在第二步里我们使用了
#{数字(0开始)或者param+数字(1开始)}
得到传入的数据
那么我们如果想用抽象方法的形参的名字获取数据可行吗?
很遗憾答案是否
mybatis会报错,原因是找不到名字
使用@Param注解处理
mybatis提供了@Param注解来起别名让它能找到形参
使用
在接口的抽象方法中
User selByName2(@Param("name") String name,@Param("password") String password);
这样就可以使用注解指定的别名来寻找形参
xml文件中
<select id="selByName2" resultType="user">
select * from user where name=#{name} and password=#{password}
</select>
这里的#{键} 键的名称和之前注解里的是对应的
动态SQL
根据条件的不同,SQL语句也会随之动态的改变
在mybatis中动态sql的实现方式是在xml配置文件中使用了各种各样的标签,来动态产生sql语句
mybatis使用了基于OGNL的表达式,我理解为应该和jsp里面学习的el表达式同类的东西
1. if标签
作用:用于条件的判断,使用方式我理解和jstl标签差不多
<select id="sel" resultType="user">
select * from user
<if test="username != null and username != ''">
where name=#{username}
</if>
<if test="password != null and password != ''">
and password=#{password}
</if>
</select>
test属性:值代表是否输出if标签内的内容,注意里面的属性名称是用的别名,需要在接口中用@Param注解声明,而且两个属性的判断之间不能用&&或||连接需要使用and或者or来连接。
小bug:上面的代码看似还行。其实出现了严重的bug,如果我们没有传入username那么第一个if内容不会输出那么直接输入第二个if的内容,但是第二个if里面开始是and关键字而不是where,这样就导致会直接报sql语句错误
小聪明解决法:动用一点小聪明可以解决上述小bug,在sql语句后面写入where 1=1所有的if里面的语句全部写成and开头就没问题了
<select id="sel" resultType="user">
select * from user where 1=1
<if test="username != null and username != ''">
and name=#{username}
</if>
<if test="password != null and password != ''">
and password=#{password}
</if>
</select>
2. where标签
之前使用if出现了一个小bug问题
虽然我们也用耍小聪明的办法解决了该问题,但是小聪明始终不是长久之计,mybatis提供了官方的解决方案,where标签
<select id="sel" resultType="user">
select * from user
<where>
<if test="username != null and username != ''">
and name=#{username}
</if>
<if test="password != null and password != ''">
and password=#{password}
</if>
</where>
</select>
在if语句外面包括where标签,即可解决这个问题
where 会检测第一个内容的and,并把其改为where
3. choose (when, otherwise)标签组
作用:进行多分支判断,类似于jstl的choose标签
<select id="sel3" resultType="user">
select * from user
<where>
<choose>
<when test="username != null and username != ''">
and name = #{username}
</when>
<when test="password != null and password != ''">
and password = #{username}
</when>
<otherwise>
and 1=1
</otherwise>
</choose>
</where>
</select>
特点:choose下面的所有when或者otherwise标签只会执行一个,相当于switch 下面的case和default
4. set标签
作用:类似于where标签,为修改语句添加set关键字
<update id="updUser" parameterType="user">
update user
<set>
<if test="password != null and password != ''">
password = #{password},
</if>
</set>
where name=#{name}
</update>
5. trim标签
**作用:**相当于where和set的泛用,where和set是trim的特殊情况
<update id="updUser2" parameterType="user">
update user
<trim prefix="set" prefixOverrides="" suffix="" suffixOverrides=",">
password=#{password}
</trim>
where name=#{name}
</update>
四个属性:
属性名 | 作用 |
---|---|
prefix | 前缀,表示向前面添加内容 |
prefixOverrides | 从前面删除内容 |
suffix | 后缀,表示向后面添加内容 |
suffixOverrides | 从后面删除内容 |
使用trim标签完全可以模拟where标签或者set标签,而且可以做到比二者更灵活
6. foreach标签
作用:用于遍历一个list集合绑定在sql语句上
<select id="selIn" parameterType="list" resultType="user">
select * from user where name in
<foreach collection="list" open="(" separator="," close=")" item="item">
#{item}
</foreach>
</select>
由于不是很灵活,foreach标签,一般用于in的值的绑定
属性名 | 作用 |
---|---|
collection | 要遍历的集合名,注意配置别名 |
open | 开始添加的内容,in后面需要()所以一般添加"(" |
separator | 内容用什么分割 |
close | 结束添加的内容 |
item | 代表当前遍历的元素 |
index | 代表当前遍历元素的索引 |
7. bind标签
**作用:**为元素绑定参数,主要用于模糊查询使用
<select id="sel4" resultType="user">
select * from user
<where>
<if test="username != null and username != ''">
<bind name="username" value="'%' + username + '%'"/>
and name like #{username}
</if>
</where>
</select>
属性名 | 作用 |
---|---|
name | 属性配置的别名 |
value | 替换属性的值的值 |
8. sql和include标签
**作用:**做到sql语句的复用
步骤:
- 在mapper标签下定义sql标签,sql标签下写需要复用的语句
<sql id="mySql">
name, password
</sql>
属性:id用于标识sql语句
2. 在需要复用sql的地方使用include复用语句
<select id="selByName2" resultType="user">
select
<include refid="mySql"/>
from user where name=#{name} and password=#{password}
</select>
属性:refid写如要引用的sql语句的id
Q.E.D.