MyBatis深度解析:原理、实战与参数传递全攻略,帮你秒懂ORM框架

mybatis的原理和实现

mybatis底层为itbatis。有人问了,为什么用mybatis不用itbatis?

mybatis介绍

mybatis的xml配置

首先,我们介绍一下mybatis的使用方法

如图所示

我们在xml文件里使用权限定符来定义映射的接口
id为接口里面的方法

id与namespace结合引到某接口里的方法 而resuleType呢

dml语句即:增加删除修改不需要设置,因为这三者返回的是影响的行数

我们只需要设置select标签的返回值。

返回值怎么设置呢?参数怎么设置呢?

为什么这个xml文件里面的select参数是#{id}的形式?

id可以换为其它的吗?

这些问题,我们稍后会讲,先回归到刚才的问题上。

我们实践后会观察到,mybatis的配置方式,非常的方便

编写namespace时,会有相应的提示

以及,id的对应关系使得我们写代码过程中会明白自己调用的是什么方法,以及方便后续其他人员的参考。

返回值类型呢我们暂且使用权限定符,写的时候会发现也有提示,方便。

mybatis的测试

写完了xml文件,怎么调用呢?

如图

读取相关的配置文件,同时获得mapper接口的类

之后调用这个接口的各种方法以实现sql语句的执行

itbatis对比

itbatis的xml配置

ok刚说的过程中我们了解到,mybatis有很多方便之处

这些方便是因为原有的机制并不方便

ok,我们来看看mybatis底层的itbatis是怎么写相关xml文件的

刚才我们写了什么?接口,接口对应的xml文件

而这里,不需要!

刚才我们的namespace以及id是分别对应了接口的位置以及接口里面的方法

而这里不需要,namespace随便写,id随便写

配置方法具体如图

itbatis的使用方法

如图

调用时只需要对应上相关的namespace以及id的关系即可

二者明明随便,但是,没有提示符号,同时参数是Object的形式,当是其它形式的时候,需要提前声明,很麻烦,以及在编写代码过程中不一定能写对

取值符号

我们观察到刚才写select标签的时候,我们引入参数id的时候是#{id},这个#{}是一种引入参数的方法

而这个id则是另一种原因,等会在传入的类型处会讲

为什么用#{}呢?有没有其他的?答案是有的

另一种是${}。这两者有什么区别呢?我们需要看具体的实现过程

这时候呢,我们就需要在总配置文件里面开启一个日志打印。

让日志能够打印到控制台上

之后呢,select设置两种模式

#{}参数引入

当是#{}的时候,如图,输出

可以看到当是#{}的时候,显示的是emp_id这个东西=? 后面又跟了一个参数的复数之后:1

${}参数引入

配置文件里面改为${}引入

在测试环境里运行,运行结果如图

这次发现,我们这里直接是数据库某以属性名=具体的数字1.而参数后面没有跟任何东西

也就是说${}是直接将东西拼接上去了

两种参数引入方式的总结

总结来看,#{}是,${}是字符串的拼接,也就是说结果为参数=字符串

#{}引入的东西会被当成一个单独的值

#{}这个有什么好处呢?比如说,这个题里面,我们设置的emp_id为varchar类型

当用户录入的id为1=1时候

${}会执行emp_id=1=1这句话,会报错

而#{}执行这句话时是 emp_id='1=1'。等于的是一个具体的东西,而不会受到=的影响

传入的类型

单个简单类型

如图,我们传入的是id这个一个单个的参数,怎么写呢?

首先用#{}会安全一点,其次,直接引入即可,这个key(识别参数的标识),可以随便写,不仅仅可以写#{id},也可以写#{a},随便写,但是为了规范,写为id较好,方便后续相关人员的识别。

多个简单类型

如图,我们的参数为String的name 和Double的salary

总共有三种引入方式

arg引入

前两种为按照顺序引入

从0开始的arg0 arg1。arg0对应的是第一个参数name,arg1对应的是第二个参数salary

param引入

从1开始的param1 param2。对应的为按照参数引入的顺序,比如我们这次引入了两个参数那么param1是name,param2是salary

@param定义

我们在mapper接口类里面的参数面前添加@param备注,备注里面的名字,即为我们要在xml文件里面写的引入的参数的名字

包装类

比如,这次,我们引入的参数的Employee类

而它有三个属性empId,empName以及empSalary

怎么引入参数呢?

只需要一个一个的对应即可,比如属性为empName,那么在参数引入里面直接写empName即可

Map参数

当,参数为map的时候怎么引入呢?

只需要设置Map类型,以及在test类里面map的每一个key也就是属性名 对上相应的具体的属性值即可

mapper里面写的接口如下

xml文件引入的如下

test类里面如下

import com.atguigu.mapper.EmployeeMapper;
import com.atguigu.pojo.Employee;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;


public class MybatisTes {
    @Test
    public void test01() throws IOException {
        //1.读取外部配置文件
        InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
        //创建sqlSessionFactory
        SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);
        //获取SqlSession对象
        SqlSession sqlSession = build.openSession();
        //获取mapper 对象
        EmployeeMapper m = sqlSession.getMapper(EmployeeMapper.class);
        //管理资源或提交事务
        Map<String,Object> param=new HashMap<>();
        param.put("name","张三");
        param.put("salary",8000.0);
        int employee = m.insertEmpMap(param);
        System.out.println("employee"+employee);
        sqlSession.close();


    }
}

返回值

单个简单类型

如图mapper里面返回为String类型

xml里如图

我们的result为string,String为包装数据类型,我们用它首字母的小写

也可以用具体的权限定符即java.long.String

当遇到基本数据类型比如int时候 我们写成_int

包装类型

权限定符

当返回的是包装类比如Employee时

我们可以使用全限定符,即具体的位置,比如com.Employee

但是这样太麻烦了,当然了,还有另外两种方式

使用typeAliases定义别名

在总配置文件里面
1.给类单独定义别名
<typeAliases>
<typeAlias type="com.atguigu.pojo.Employee" alias="ergouzi"/>
</typeAliases>
2.批量定义
<typeAliases>
批量给包下的东西其别名,别名就是类的缩写
<package name="com.atguigu.pojo"/>
</typeAliases>

使用@Alias注释

在目标返回值类型的类上面写上@Alias即可

mapper类型

mapper里面的配置如图,返回值为Map<String,Objece>

xml配置如下

<select id="selectEmpNameAndMaxSalary" resultType="map">
    SELECT
    emp_name 员工姓名,
    emp_salary 员工工资,
    (SELECT AVG(emp_salary) FROM t_emp) 部门平均工资
    FROM t_emp WHERE emp_salary=(
    SELECT MAX(emp_salary) FROM t_emp
    )
</select>

接收的时候使用String,Object的Map类型接收即可

之后通过foreach语句,对该map的每一个键值对都进行遍历

五种标签的使用

当我们要动态的改变语句的时候,会发现传统的方法很难,我们一个一个语句写

但是当,用户要筛选省份,地址,等各种条件,我们总不能一种一种结果的去敲吧?

这样显然费时费力,所以我们就有了下面这些标签的出现。

where以及if标签

<select id="query" resultType="employee">
        select * from t_emp
        <where>
            <if test="name != null">
                emp_name=#{name}
            </if>
            <if test="salary !=null and salary &gt; 100">
                and emp_salary=#{salary}
            </if>
        </where>
    </select>

对比这个代码以及原代码

select * from t_emp where  emp_name=#{name} and emp_salary=#{salary}

当名字为空,不作为选择对象时,直接就舍弃了,当salary不达到筛选条件时,也直接不用。

那有人就问了,为什么要多加一个where,我只用这里面的if不行吗?

我们来试试看,当第一个if不成立,第二个if成立的时候,会发现,where and ...这句话有明显的语法错误

这怎么办啊?这怎么实现动态筛选啊

这时候就有where标签的出现了,省略写where,然后当有多余的and的时候会自动的进行过滤

set标签

当我们写动态的更新语句时,例如下面这句时

update t_emp set emp_name=#{empName},emp_salary=#{empSalary} where emp_id=#{empId}

如果我设置empName不设为参考元素怎么办?我加入if?但是多一个逗号怎么处理?这时候就跟where标签出现处理and这个一样,set出现了,set标签可以省略set以及去掉多余的逗号

update t_emp
        <set>
            <if test="empName !=null">
                emp_name=#{empName},
            </if>
            <if test="empSalary">
                emp_salary=#{empSalary}
            </if>
        </set>

        where emp_id=#{empId}

trim标签

trim标签,可以当作前两者的替换,只不过,写起来比较的多,在每句前面加上什么,去掉什么等等

<select id="querytrim" resultType="employee">
        select * from t_emp
<!--        前面加where 同时去掉多余的and or这种修饰符-->
        <trim prefix="where" prefixOverrides="and|or">
            <if test="name != null">
                emp_name=#{name}
            </if>
            <!--        如果传入属性就判断相等
                如果不传入就不添加条件怎么弄呢?
                怎么动态呢? 不推荐直接写符 写实体符号&gt;
                但是拼接符号 where等都不满足怎么办
                添加where标签
                    1.不满足where时,自动删除where
                    2.多余and和or时候,自动去掉多余的or 和 and
            -->
            <if test="salary !=null and salary &gt; 100">
                and emp_salary=#{salary}
            </if>
        </trim>
    </select>

如图,代替where标签,在trim里面备注,语句的前面要多一个where,同时,语句前面遇到and时候也要用prefixOverrides这个属性去掉

choose标签

相当于是switch case语句 当第一个条件成立,选第一个,全部行就选otherwise

<select id="queryChoose" resultType="employee">
        select * from t_emp
        where
        <choose>
            <when test="name != null">emp_name=#{name}</when>
            <when test="salary !=null">emp_salary=#{salary}</when>
            <otherwise>1=1</otherwise>
        </choose>
    </select>

foreach标签

当我们要插入多条语句,同时只想用一句话来写怎么办?

首先,输入一个集合类型,用xml语句进行批量的判断

比如下面这个insert语句

每一项之间加,为分隔符,批量的插入即

<insert id="insertBatch">
        insert into t_emp(emp_name,emp_salary)
        values
        <foreach collection="list" separator="," item="itema">
            (#{itema.empName},#{itema.empSalary})
        </foreach>
    </insert>

上面还只是一个语句的执行

当我们要批量update时,我们需要重写语句,怎么办?那就所有的foreach,记得每句加上个;哦

 <update id="updateBatch">
<!--        没地方遍历?整体遍历
            如果一个标签设计多个语句,需要设计多个语句
            ?allowMultiQueries=true这样允许多语句执行
-->
        <foreach collection="list" item="emp">
            update t_emp set emp_name=#{emp.empName},emp_salary=#{emp.empSalary}
            where emp_id=#{emp.empId};
        </foreach>
    </update>

Mybatis XML配置总结

ok,就讲这么多吧,我们再简单回顾一下

xml配置时需要使用接口权限定符

传入参数有一种,多种,包装类,Map参数

返回值类型有一种,包装类,Map类型

以及五种标签where,set,trim,choose,foreach等

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值