Mybatis SQL mapping文件详解

本文详细介绍了Mybatis映射文件中的SQL操作,包括insert、update、delete、select元素的使用,特别是select元素的参数传递、处理集合结果、自定义resultMap及联合查询等。此外,文章还深入讲解了Mybatis的动态SQL功能,如if、foreach、choose、set等元素的应用,并探讨了一级缓存和二级缓存的工作原理、配置以及在不同场景下的使用策略,最后讨论了如何整合第三方缓存。
摘要由CSDN通过智能技术生成

​ 在之前我们学习了mybatis的全局配置文件,下面我们开始学习mybatis的映射文件,在映射文件中,可以编写以下的顶级元素标签:

cache – 该命名空间的缓存配置。
cache-ref – 引用其它命名空间的缓存配置。
resultMap – 描述如何从数据库结果集中加载对象,是最复杂也是最强大的元素。
parameterMap – 老式风格的参数映射。此元素已被废弃,并可能在将来被移除!请使用行内参数映射。文档中不会介绍此元素。
sql – 可被其它语句引用的可重用语句块。
insert – 映射插入语句。
update – 映射更新语句。
delete – 映射删除语句。
select – 映射查询语句。

​ 在每个顶级元素标签中可以添加很多个属性,下面我们开始详细了解下具体的配置。

1、insert、update、delete元素

属性 描述
id 在命名空间中唯一的标识符,可以被用来引用这条语句。
parameterType 将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)。
parameterMap 用于引用外部 parameterMap 的属性,目前已被废弃。请使用行内参数映射和 parameterType 属性。
flushCache 将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:(对 insert、update 和 delete 语句)true。
timeout 这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为未设置(unset)(依赖数据库驱动)。
statementType 可选 STATEMENT,PREPARED 或 CALLABLE。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。
useGeneratedKeys (仅适用于 insert 和 update)这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server 这样的关系型数据库管理系统的自动递增字段),默认值:false。
keyProperty (仅适用于 insert 和 update)指定能够唯一识别对象的属性,MyBatis 会使用 getGeneratedKeys 的返回值或 insert 语句的 selectKey 子元素设置它的值,默认值:未设置(unset)。如果生成列不止一个,可以用逗号分隔多个属性名称。
keyColumn (仅适用于 insert 和 update)设置生成键值在表中的列名,在某些数据库(像 PostgreSQL)中,当主键列不是表中的第一列的时候,是必须设置的。如果生成列不止一个,可以用逗号分隔多个属性名称。
databaseId 如果配置了数据库厂商标识(databaseIdProvider),MyBatis 会加载所有不带 databaseId 或匹配当前 databaseId 的语句;如果带和不带的语句都有,则不带的会被忽略。
	<!--如果数据库支持自增可以使用这样的方式-->
    <insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
        insert into user(user_name) values(#{userName})
    </insert>
    <!--如果数据库不支持自增的话,那么可以使用如下的方式进行赋值查询-->
    <insert id="insertUser2" >
        <selectKey order="BEFORE" keyProperty="id" resultType="integer">
            select max(id)+1 from user
        </selectKey>
        insert into user(id,user_name) values(#{id},#{userName})
    </insert>

2、select元素

1、select的参数传递
<!--
    当查询语句中包含多个参数的是,如果使用#{属性名称}就无法获取具体的值了,那么应该如何使用呢?
        下面就是mybatis的参数传递方式
        1、如果是单个参数,
            基本类型:使用#{随便写}
            引用类型:使用#{类的属性名称}
        2、多个参数:
            当查询的时候传入多个参数的时候,就无法简单的通过#{参数名}来获取值了,
            只能通过arg0,arg1...或者param1,param2等方式来获取值
            原因就在于,mybatis在传入多个参数的时候,会将这些参数封装到一个map中,此时map中的key就是
            arg0,arg1,param1,param2这些值,但是很明显,这样的传值方式不是很友好,没有办法根据参数的名称来
            获取具体的值,因此可以使用如下的方式来指定参数的key是什么
            Emp selectEmpByNoAndName(@Param("empno") Integer empno, @Param("ename") String ename);
                也就是通过@Param来指定存入map中的key值是什么
        3、使用map来传递参数:
                依然是直接使用#{key}来获取具体的属性值
    -->
    <select id="selectEmpByNoAndName" resultType="com.lw.bean.Emp">
        select * from emp where empno=#{empno} and ename=#{ename}
    </select>

    <select id="selectEmpByNoAndName2" resultType="com.lw.bean.Emp">
        select * from emp where empno=#{empno} and ename=#{ename}
    </select>
2、参数的取值方式

​ 在xml文件中编写sql语句的时候有两种取值的方式,分别是#{}和${},下面来看一下他们之间的区别:

 <!--
        当使用#{}来获取值的时候会发现打印的sql语句如下:
            select * from emp where empno=? and ename=?
        当使用${}来获取值的时候会发现打印的sql语句如下:
            select * from emp where empno=7369 and ename='SMITH'
        通过刚刚的案例大家已经发现了存在的问题了,
        使用#{}方式进行取值:采用的是参数预编译的方式,参数的位置使用?进行替代,不会出现sql注入的问题
        使用${}方式进行取值:采用的是直接跟sql语句进行拼接的方式

		此处大家需要注意,如果我们的sql语句中的某些值不支持参数预编译,那么就必须要使用${}的方式来取值了
    -->
    <select id="selectEmpByNoAndName" resultType="com.lw.bean.Emp">
        select * from #{t} where empno=${empno} and ename=${ename}
    </select>
3、处理集合返回结果

EmpDao.xml

<!--当返回值的结果是集合的时候,返回值的类型依然写的是集合中具体的类型-->
    <select id="selectAllEmp" resultType="com.lw.bean.Emp">
        select  * from emp
    </select>
<!--在查询的时候可以设置返回值的类型为map,当mybatis查询完成之后会把列的名称作为key
    列的值作为value,转换到map中
    -->
    <select id="selectEmpByEmpReturnMap" resultType="map">
        select * from emp where empno = #{empno}
    </select>

    <!--注意,当返回的结果是一个集合对象的是,返回值的类型一定要写集合具体value的类型
    同时在dao的方法上要添加@MapKey的注解,来设置key是什么结果
    @MapKey("empno")
    Map<Integer,Emp> getAllEmpReturnMap();-->
    <select id="getAllEmpReturnMap" resultType="com.lw.bean.Emp">
        select * from emp
    </select>

UserDao.java

package com.lw.dao;

import com.lw.bean.Emp;
import org.apache.ibatis.annotations.MapKey;
import org.apache.ibatis.annotations.Param;

import java.util.List;
import java.util.Map;

public interface EmpDao {
   

    public Emp findEmpByEmpno(Integer empno);

    public int updateEmp(Emp emp);

    public int deleteEmp(Integer empno);

    public int insertEmp(Emp emp);

    Emp selectEmpByNoAndName(@Param("empno") Integer empno, @Param("ename") String ename,@Param("t") String tablename);
    Emp selectEmpByNoAndName2(Map<String,Object> map);

    List<Emp> selectAllEmp();

    Map<String,Object> selectEmpByEmpReturnMap(Integer empno);

    @MapKey("empno")
    Map<Integer,Emp> getAllEmpReturnMap();
}
4、自定义结果集—resultMap

Dog.java

package com.lw.bean;

public class Dog {
   
    private Integer id;
    private String name;
    private Integer age;
    private String gender;

    public Integer getId() {
   
        return id;
    }

    public void setId(Integer id) {
   
        this.id = id;
    }

    public String getName() {
   
        return name;
    }

    public void setName(String name) {
   
        this.name = name;
    }

    public Integer getAge() {
   
        return age;
    }

    public void setAge(Integer age) {
   
        this.age = age;
    }

    public String getGender() {
   
        return gender;
    }

    public void setGender(String gender) {
   
        this.gender = gender;
    }

    @Override
    public String toString() {
   
        return "Dog{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                '}';
    }
}

dog.sql

/*
Navicat MySQL Data Transfer

Source Server         : node01
Source Server Version : 50729
Source Host           : 192.168.85.111:3306
Source Database       : demo

Target Server Type    : MYSQL
Target Server Version : 50729
File Encoding         : 65001

Date: 2020-03-24 23:54:22
*/

SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for `dog`
-- ----------------------------
DROP TABLE IF EXISTS `dog`;
CREATE TABLE `dog` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `dname` varchar(255) DEFAULT NULL,
  `dage` int(11) DEFAULT NULL,
  `dgender` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of dog
-- ----------------------------
INSERT INTO dog VALUES ('1', '大黄', '1', '雄');
INSERT INTO dog VALUES ('2', '二黄', '2', '雌');
INSERT INTO dog VALUES ('3', '三黄', '3', '雄');

DogDao.java

package com.lw.dao;

import com.lw.bean.Dog;

public interface DogDao {
   

    public Dog selectDogById(Integer id);
}

DogDao.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lw.dao.DogDao">
   <!--
   在使用mybatis进行查询的时候,mybatis默认会帮我们进行结果的封装,但是要求列名跟属性名称一一对应上
   在实际的使用过程中,我们会发现有时候数据库中的列名跟我们类中的属性名并不是一一对应的,此时就需要起别名
   起别名有两种实现方式:
      1、在编写sql语句的时候添加别名
      2、自定义封装结果集
   -->
   <!--根据查询的数据进行结果的封装要使用resultMap属性,表示使用自定义规则-->
   <select id="selectDogById" resultMap="myDog">
      select * from dog where id = #{id}
   </select>

   <!--自定义结果集,将每一个列的数据跟javaBean的对象属性对应起来
   type:表示为哪一个javaBean对象进行对应
   id:唯一标识,方便其他属性标签进行引用
   -->
   <resultMap id="myDog" type="com.lw.bean.Dog">
      <!--
      指定主键列的对应规则:
      column:表示表中的主键列
      property:指定javaBean的属性
      -->
      <id column="id" property="id"></id>
      <!--设置其他列的对应关系-->
      <result column="dname" property="name"></result>
      <result column="dage" property="age"></result>
      <result column="dgender" property="gender"></result>
   </resultMap>
   <!--可以在sql语句中写别名-->
 <!--  <select id="selectDogById" resultType="com.lw.bean.Dog">
      select id id,dname name,dage age,dgender gender from dog where id = #{id}
   </select>-->

   <!--这种方式是查询不到任何结果的,因为属性名跟列名并不是一一对应的-->
  <!-- <select id="selectDogById" resultType="com.lw.bean.Dog">
      select * from dog where id = #{id}
   </select>-->
</mapper>
5、联合查询

emp.java

package com.lw.bean;

import java.util.Date;

public class Emp {
   

    private Integer empno;
    private String ename;
    private String job;
    private Integer mgr;
    private Date hiredate;
    private Double sal;
    private Double common;
    private Dept dept;

    public Emp() {
   
    }

    public Emp(Integer empno, String ename) {
   
        this.empno = empno;
        this.ename = ename;
    }

    public Emp(Integer empno, String ename, String job, Integer mgr, Date hiredate, Double sal, Double common, Dept dept) {
   
        this.empno = empno;
        this.ename = ename;
        this.job = job;
        this.mgr = mgr;
        this.hiredate = hiredate;
        this.sal = sal;
        this.common = common;
        this.dept = dept;
    }

    public Integer getEmpno() 
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值