Mybatis快速入门(二)

简介: Mybatis快速入门(二)

四、MyBatis-映射文件



MyBatis 的真正强大在于它的语句映射,这是它的魔力所在


映射文件指导着Mybatis如何进行数据库CRUD,有着非常重要的意义


cache-命名空间的二级缓存配置


cache-ref-其他命名空间缓存配置的引用


resultMap-自定义结果集映射


sql抽取可重用语句块


insert -映射插入语句


update-映射更新语句


delete -映射删除语句


select-映射查询语句


SQL映射文件一般命名为接口名+Mapper


如EmployeeMapper、EmployeeMapperpro、EmployeeMapperpromax


下面我们来分别介绍sql映射文件中的这些元素~


4.1 参数(Parameters)传递


单个参数

可以接受基本类型,对象类型,集合类型的值。这种情况MyBatis可值接使用这个参数﹐不需要经过任何处理。


多个参数

任意多个参数,都会被MyBatis重新包装成一个Map传入。Map的key是param1 , param2 ,0,1…,值就是参数的值。


命名参数

为参数使用@Param起一个名字,MyBatis就会将这些参数封装进map中, key就是我们自己指定的名字


POJO

当这些参数属于我们业务POJO时,我们直接传递POJO


Map

我们也可以封装多个参数为map ,直接传递


4.2 参数处理


参数位置支持的属性


javaType、jdbcType、mode、numericScale、resultMap、typeHandler、jdbcTypeName


实际上通常被设置的是∶


可能为空的列名指定jdbcType


#{key}:获取参数的值,预编译到SQL中。安全。


${key}:获取参数的值,拼接到SQL中。有SQL注入问题。ORDER BY ${name}


一般选择#{key}的方式来获取参数的值


4.3 增删改查元素


Select元素来定义查询操作。


ld:唯一标识符。


用来引用这条语句,需要和接口的方法名一致


parameterType :参数类型。


可以不传,MyBatis会根据TypeHandler自动推断


resultType:返回值类型。


别名或者全类名﹐如果返回的是集合﹐定义集合中元素的类型。不能和resultMap同时使用


resultMap:自定义返回值类型


外部resultMap的命名引用。和resultType属性不能同时使用


<select id="getEmpById" resultType="emp">    select * from tbl_employee    where id = #{id}</select>


insert, update 和 delete和上述查询其实查不到哪里去啦,差不多都一样的啦~


<insert id="insert" parameterType="com.caq.mybatis.bean.Employee" useGeneratedKeys="true" keyProperty="id">    insert into tbl_employee(last_name,email,gender) values(#{lastName},#{email},#{gender})</insert><update id="updateEmp">    update tbl_employee    set last_name=#{lastName},email=#{email},gender=#{gender} where id = #{id}</update><delete id="deleteEmpById">    delete from tbl_employee where id = #{id}</delete>


不难,主要是我们sql语句的书写


要注意的点是,删除修改数据库中的字段,我们传的参数都是一个javabean对象


如果数我们查的数据中不只有属性还有个对象改怎么查呢?


我们可以想象如下场景:


查询Employee的同时查询员工对应的部门

场景一:

查询Employee的同时查询员工对应的部门

Employee===Department

一个员工有与之对应的部门信息;


联合查询:级联属型封装结果集


<resultMap id="MyEmpPlus" type="com.caq.mybatis.bean.Employee">    <id column="id" property="id"/>    <result column="last_name" property="lastName"/>    <result column="gender" property="gender"/>    <result column="did" property="dept.id"/>    <result column="dept_name" property="dept.departmentName"/></resultMap><select id="getEmpAndDept" resultMap="MyEmpPlus">    SELECT e.id id,e.last_name last_name,e.gender gender,e.d_id d_id,d.id did,d.dept_name dept_name    FROM tbl_employee e,tbl_dept d    where e.d_id = d.id    and e.id = 1</select>


上述方式的确可以解决这个问题


但是你看它是不是写的太麻烦了啊,那有没有简单的方法查询呢?


association可以指定联合的javaBean对象

指定哪个属型是联合的对象

javaType指定属型对象的类型【不能省略】

使用association定义关联的单个对象的封装规则


<resultMap id="MyEmpByStep" type="com.caq.mybatis.bean.Employee">
    <!--        先按照员工id查询员工信息-->
    <!--        根据查询员工信息中的d_id值去查部门查处部门信息--> 
    <!--        部门设置到员工中-->  
    <id column="id" property="id"/>  
    <result column="last_name" property="lastName"/> 
    <result column="email" property="email"/>  
    <result column="gender" property="gender"/> 
    <!--        association来定义关联对象的封装规则            select表明当前属性是调用sekect指定的方法查出的结果            流程:使用select指定的方法(传入column指定的这列参数的值)查出对象,并封装给property指定的属性--> 
    <association property="dept"select="com.caq.mybatis.dao.DepartmentMapper.getDeptById" column="d_id"> 
    </association>
</resultMap>
<select id="getEmpByIdStep" resultMap="MyEmpByStep"> 
    select * from tbl_employee where id = #{id}
</select>


select:调用目标的方法查询当前属性的值


column:将指定列的值传入目标方法


没错我们可以用association来进行查询,也就是分布查询。


先按照员工id查询员工信息

根据查询员工信息中的d_id值去查部门查处部门信息

部门设置到员工中

从这里就能看出Mybatis的灵活,处理一些很复杂的查询的时候association能帮我们解决头痛的问题


4.4 SQL


这个元素可以用来定义可重用的 SQL 代码片段,以便在其它语句中使用。 参数可以静态地(在加载的时候)确定下来,并且可以在不同的 include 元素中定义不同的参数值。


<sql id="userColumns"> ${alias}.id,${alias}.username,${alias}.password </sql>


<select id="selectUsers" resultType="map">    select    <include refid="userColumns">        <property name="alias" value="t1"/>    </include>,       <include refid="userColumns">        <property name="alias" value="t2"/>    </include>    from some_table t1 cross join some_table t2</select>


一般我们会把重复的sql字段提取出一个sql,然后不同的语句用这个sql字段的时候我们调这个提取出来的sql即可


4.5 自动映射


全局setting设置


autoMappingBehavior默认是PARTIAL,开启自动映射的功能。唯一的要求是列名和javaBean属性名一致―如果autoMappingBehavior设置为null则会取消自动映射一数据库字段命名规范,POJO属性符合驼峰命名法,如A_COLUMN→>aColumn ,我们可以开启自动驼峰命名规则映射功能,mapUnderscoreToCamelCase=true


自定义resultMap ,实现高级结果集映射。


4.6 resultMap


一些参数的介绍


constructor -类在实例化时,用来注入结果到构造方法中


id 一个ID结果;标记结果作为ID可以帮助提高整体效能


result一注入到字段或JavaBean属性的普通结果


association 一个复杂的类型关联;许多结果将包成这种类型


嵌入结果映射


结果映射自身的关联,或者参考一个


collection 复杂类型的集


嵌入结果映射 结果映射自身的集,或者参考一个


discriminator 使用结果值来决定使用哪个结果映射


case-基于某些值的结果映射

嵌入结果映射-这种情形结果也映射它本身,因此可以包含很多相同的元素,或者它可以参照个外部的结果映射。


<resultMap id="MyEmp" type="com.caq.mybatis.bean.Employee">
       <!--            指定主键列的封装规则:            id定义主键列的话底层会有优化            column指定哪一列            property指定对应的javaBean属性-->        
       <id column="id" property="id"/>
       <!--        result定义普通列封装规则--> 
       <result column="last_name" property="lastName"/>
       <!--        其他不指定的列会自动封装,不过我们既然自定义了那就把字段都写上-->  
       <result column="gender" property="gender"/> 
       <result column="email" property="email"/> 
</resultMap>    
<!--        id就是方法名-->
<!--    <select id="getEmpById" resultType="emp">-->
<!--        select *-->
<!--        from mybatis.tbl_employee-->
<!--        where id = #{id};-->
<!--    </select>-->    
<select id="getEmpById" resultMap="MyEmp">  
    select * from tbl_employee where id = #{id}; 
</select>


4.7 鉴别器


有时候,一个数据库查询可能会返回多个不同的结果集(但总体上还是有一定的联系的)。 鉴别器(discriminator)元素就是被设计来应对这种情况的,另外也能处理其它情况,例如类的继承层次结构。 鉴别器的概念很好理解——它很像 Java 语言中的 switch 语句。


column指定判定的列名,javaType列值对应的java类型


男生,如果是男生,把last_name这一列的值赋给email,女生则查询出所在部门信息


<resultMap id="MyEmpDis" type="com.caq.mybatis.bean.Employee">
    <id column="id" property="id"/>
    <result column="last_name" property="lastName"/>
    <result column="email" property="email"/>
    <result column="gender" property="gender"/>
    <!--        column指定判定的列名,javaType列值对应的java类型-->
    <discriminator javaType="string" column="gender">
        <!--            女生-->
        <case value="0" resultType="com.caq.mybatis.bean.Employee">
            <association property="dept"
                         select="com.caq.mybatis.dao.DepartmentMapper.getDeptById"
                         column="d_id">
            </association>
        </case>
        <!--            男生,如果是男生,把last_name这一列的值赋给email-->
        <case value="1" resultType="com.caq.mybatis.bean.Employee">
            <id column="id" property="id"/>
            <result column="last_name" property="lastName"/>
            <result column="last_name" property="email"/>
            <result column="gender" property="gender"/>
        </case>
    </discriminator>
</resultMap>
<select id="getEmpByIdStep" resultMap="MyEmpDis">
    SELECT * FROM tbl_employee WHERE id = #{id};
</select>


这个很好理解的,我还是把测试结果写出来


//    根据id分布查员工信息@Testpublic void test03() throws IOException {    SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();    SqlSession openSession = sqlSessionFactory.openSession();      try {        EmployeeMapperPlus mapper = openSession.getMapper(EmployeeMapperPlus.class);          Employee empByIdStep = mapper.getEmpByIdStep(4);              System.out.println(empByIdStep);        System.out.println(empByIdStep.getDept());    } finally {        openSession.close();    }}


我们查询id为4的员工,根据我们前面写的sql映射文件,如果它的性别是男则他的邮件地址就是它的姓名,如果他的性别是女那么就能打印出她的部门信息(查部门信息又是一个新的对象我们用的association分步查询)


image.png


显示结果分别如下:


Employee{id=4, lastName=‘jerry2’, email=‘jerry2’, gender=‘1’}
null
Employee{id=1, lastName=‘tom’, email=‘tom@caq.com’, gender=‘0’}
Department{id=1, departmentName=‘开发’}


五、MyBatis-动态SQL



动态SQL是MyBatis强大特性之一。极大的简化我们拼装SQL的操作,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。。动态SQL元素和使用JSTL或其他类似基于XML的文本处理器相似。MyBatis采用功能强大的基于OGNL的表达式来简化操作。


if
choose (when, otherwise)
trim (where,set)
foreach


5.1 if


使用动态 SQL 最常见情景是根据条件包含 where 子句的一部分。


比如我们有很多字段,那我们写条件的时候要在where后面写很长的判断条件,那么有了if我们就可以根据if判断条件。如果条件成立则添加不添加。


遇见特殊符号其实可以写转义字符


HTML 字符实体 (w3school.com.cn)


我们可以去这里寻找特殊符号对应的转义字符!


<select id="getEmpByConditionIf" resultType="com.caq.mybatis.bean.Employee">
    select *
    from tbl_employee
    where
    <!-- test:判定表达式(OGNL)
    OGNL参照PPT或官方文档
    从参数中取值进行判断
    遇见特殊符号其实可以写转义字符
    -->
    <if test="id!=null">
        id=#{id}
    </if>
    <if test="lastName!=null &amp;&amp; lastName != &quot;&quot;">
        and last_name like #{lastName}
    </if>
    <if test="email!=null and email.trim() != &quot;&quot;">
        and email =#{email}
    </if>
    # ognl会进行字符串与数字的转换判断
    <if test="gender==0 or gender==1">
        and gender=#{gender}
    </if>
</select>


5.2 choose、when、otherwise


<select id="getEmpByConditionChoose" resultType="com.caq.mybatis.bean.Employee">
    select *
    from tbl_employee
    <where>
        # 如果带了id就用id查,如果带了lastName就用lastName查,只会进入其中一个
        <choose>
            <when test="id!=null">
                id = #{id}
            </when>
            <when test="lastName!=null">
                last_name like #{lastName}
            </when>
            <when test="email!=null">
                email = #{email}
            </when>
            <otherwise>
                gender = 0
            </otherwise>
        </choose>
    </where>
</select>


下面我们看测试文件的结果


//    测试自定义字符串截取@Testpublic void test07 () throws IOException {    SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();    SqlSession openSession = sqlSessionFactory.openSession();    try {        EmployeeMapperDynamicSQL mapper = openSession.getMapper(EmployeeMapperDynamicSQL.class);        Employee employee = new Employee(null, null, null, null,null);        List<Employee> list = mapper.getEmpByConditionChoose(employee);        for (Employee employee1 : list) {            System.out.println(employee1);        }    } finally {        openSession.close();    }}


我们什么参数也没传入,所以她就会按照默认的来查。就是gender=0的情况


所以会出现如下结果:


Employee{id=1, lastName=‘tom’, email=‘tom@caq.com’, gender=‘0’}
Employee{id=6, lastName=‘tom’, email=‘tom@qq.com’, gender=‘0’}
Employee{id=7, lastName=‘Rose’, email=‘Rose@qq.com’, gender=‘0’}


5.3 trim、where、set


prefix="":前缀:trim标签体中是整个字符串拼串后的结果


prefixOverrides="":


前缀覆盖:去掉整个字符串前面多余的字符


suffix="":后缀


suffix给拼串后的整个字符串加上一个后缀


suffixOverrides=""


后缀覆盖:去掉整个字符串后面多余的字符


把我们容易多写少写的and去掉或者自动通过关键字加上,真是好用呢!


<select id="getEmpByConditionTrim" resultType="com.caq.mybatis.bean.Employee">
    select * from tbl_employee
    <trim prefix="where" suffixOverrides="and">
        <if test="id!=null">
            id=#{id}
        </if>
        <if test="lastName!=null &amp;&amp; lastName != &quot;&quot;">
            last_name like #{lastName} and
        </if>
        <if test="email!=null and email.trim() != &quot;&quot;">
            email =#{email} and
        </if>
        <if test="gender==0 or gender==1">
            gender=#{gender} and
        </if>
    </trim>
</select>


5.4 foreach


foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符。这个元素也不会错误地添加多余的分隔符


你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象作为集合参数传递给 foreach。当使用可迭代对象或者数组时,index 是当前迭代的序号,item 的值是本次迭代获取到的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。


有个错误一定要记得,sql语句在navicat里写或者别的sql工具。


不然在idea写错个标点要排查半天搞人心态


<insert id="addEmps">    insert into    tbl_employee(last_name,email,gender,d_id)    values    <foreach collection="emps" item="emp" separator=",">        (#{emp.lastName},#{emp.email},#{emp.gender},#{emp.dept.id})    </foreach></insert>
1
@Test    public void test08 () throws IOException {        SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();        SqlSession openSession = sqlSessionFactory.openSession();        try {            EmployeeMapperDynamicSQL mapper = openSession.getMapper(EmployeeMapperDynamicSQL.class);            ArrayList<Employee> emps = new ArrayList<>();            emps.add(new Employee(null,"tim","tim@qq.com","0",new Department(1)));            emps.add(new Employee(null,"apple","apple@163.com.com","0",new Department(2)));            mapper.addEmps(emps);            openSession.commit();            System.out.println("Success!!!");        } finally {            openSession.close();        }    }


添加成功啦~~~


5.5 bind


bind元素可以从OGNL表达式中创建一个变量并将其绑定到上下文。


<!--    List<Employee> getEmpsTestInnerParameter(Employee employee);-->
<select id="getEmpsTestInnerParameter" resultType="com.caq.mybatis.bean.Employee">
    # 可以将OGNL表达式的值绑定到一个变量中,方便后来引用这个变量的值
    <bind name="_testBind" value="'_'+lastName+'%'"/>
    select * from tbl_employee where last_name like #{_testBind}
</select>


@Test
public void test09 () throws IOException {
    SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
    SqlSession openSession = sqlSessionFactory.openSession();
    try {
        EmployeeMapperDynamicSQL mapper = openSession.getMapper(EmployeeMapperDynamicSQL .class);
        Employee employee = new Employee();
        employee.setLastName("%e%");
        List<Employee> list = mapper.getEmpsTestInnerParameter(employee);
        for (Employee employee1 : list) {
            System.out.println(employee1);
        }
    } finally {
        openSession.close();
    }
}


测试结果如下


Employee{id=3, lastName=‘jerry1’, email=‘jerry1@qq.com’, gender=‘1’}
Employee{id=4, lastName=‘jerry2’, email=‘jerry2@qq.com’, gender=‘1’}
Employee{id=5, lastName=‘jerry3’, email=‘jerry3@qq.com’, gender=‘1’}
Employee{id=8, lastName=‘jerry2’, email=‘jerry2@qq.com’, gender=‘1’}



相关文章
|
6月前
|
SQL Java 数据库连接
MyBatis快速入门以及环境搭建和CRUD的实现
MyBatis快速入门以及环境搭建和CRUD的实现
28 0
|
6月前
|
SQL Java 关系型数据库
Mybatis知识【Mybatis快速入门】第二章
Mybatis知识【Mybatis快速入门】第二章
|
2月前
|
SQL Java 数据库连接
【MyBatis-Plus】快速精通Mybatis-plus框架—快速入门
【MyBatis-Plus】快速精通Mybatis-plus框架—快速入门
49 0
|
8月前
|
Java 关系型数据库 MySQL
MyBatis(简化数据库操作的持久层框架)--快速入门[上]
MyBatis(简化数据库操作的持久层框架)--快速入门[上]
64 0
|
9月前
|
Java 关系型数据库 MySQL
SpringBoot使用Mybatis 快速入门
SpringBoot使用Mybatis 快速入门
75 0
SpringBoot使用Mybatis 快速入门
|
4月前
|
XML 算法 Java
MyBatis-Plus 实战教程一 快速入门(二)
MyBatis-Plus 实战教程一 快速入门
47 0
|
4月前
|
Java 关系型数据库 数据库连接
MyBatis-Plus 实战教程一 快速入门(一)
MyBatis-Plus 实战教程一 快速入门
48 0
|
6月前
|
XML SQL 算法
【MyBatis-Plus】快速精通Mybatis-plus框架—快速入门(下)
3.常见注解 在刚刚的入门案例中,我们仅仅引入了依赖,继承了BaseMapper就能使用MybatisPlus,非常简单。但是问题来了: MybatisPlus如何知道我们要查询的是哪张表?表中有哪些字段呢?
71 0
|
6月前
|
SQL Java 数据库连接
【MyBatis-Plus】快速精通Mybatis-plus框架—快速入门(上)
大家在日常开发中应该能发现,单表的CRUD功能代码重复度很高,也没有什么难度。而这部分代码量往往比较大,开发起来比较费时。
51 0
|
7月前
|
SQL Java 数据库连接
Mybatis快速入门
Mybatis快速入门
29 0