第一个EE框架MyBatis03

第一个EE框架MyBatis03

配置接口绑定

核心文件的配置

<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语句的复用
步骤

  1. 在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

Copyright: 采用 知识共享署名4.0 国际许可协议进行许可

Links: https://www.byfree.top/archives/mybatis03