MyBatis打工人——sql配置文件详解

这一篇,老多代码了,我的天。我用了经典的emp表和dept表做演示。加油!打工人。(看到隔壁的铁人为了调休奋战了36小时没睡,我陷入入了沉思)

Mybatis SQL映射
在SQL映射文件中,有需要的顶级元素标签: --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 的语句;如果带和不带的语句都有,则不带的会被忽略。
遇到新增、想获得自增主键怎么办?
不要怕,`useGeneratedKeys`来帮你

insert into user(id,uname,age,gender,hobby) values (#{id},#{uname},#{age},#{gender},#{hobby}) order="BEFORE" keyProperty="id" resultType="integer"> select max(id)+1 from user insert into user(id,user_name) values(#{id},#{userName})

2、select元素 这个元素是相当的麻烦,麻烦就麻烦这个顶级元素上了。秀到飞起
1、当查询语句的时候,一般我们都会动态的将属性添加到sql语句中,在Mybatis中当然也一样了
id="selectEmpById" resultType="com.kaisi.bean.Emp"> select * from emp where empno = #{qwer}

为什么引用数据类型就不行了呢?
/* 在Emp的接口中,我也是根据empno进行查询对象,但是我单参数传入的却是一个对象 (可以确定是引用类型对吧!) 那么在sql映射的配置文件 EmpDao.xml中对应的sql语句是否可以#{jqk或qwe}随便写? 测试就会发现,不能了,因为当参数为一个对象的时候,是根据具体的属性名来确定从对象中的那个属性来取到需要数值 */ public Emp selectByEmp(Emp emp);

xml文件sql如下
id="selectByEmp" resultType="com.kaisi.bean.Emp"> select * from emp where empno = #{empno}

在SQL映射文件中单参数验证完毕后,就需要验证多参数传递了
//接口定义,多参数 public Emp selectByBoth(Integer empno,Double sal);

id="selectByBoth" resultType="com.kaisi.bean.Emp"> select * from emp where empno=#{arg0} and sal>#{arg1}

【MyBatis打工人——sql配置文件详解】当然了,你如果觉得上面这种arg或者param比较low,你也可以用注解的形式
public Emp selectByBoth(@Param("empno") Integer empno,@Param("sal") Double sal);

测试类以及测试结果:想用哪种用哪种,随自己的心情
MyBatis打工人——sql配置文件详解
文章图片

参数的取值方式(插一嘴) 在xml中我们是有俩种取值方式的一种是${}一种是#{}
id="selectEmpByNoAndName" resultType="com.kaisi.bean.Emp"> select * from ${t} where empno=#{empno} and ename=${ename}

自定义结果集 当出现数据库表字段与实体类的属性不不应的时候,是无法直接进行映射的,那么就需要自定义结果集了
例如:在表中的列 我全部加了d当做开头
MyBatis打工人——sql配置文件详解
文章图片

//在Java中我定义的属性却是没有d开头的(能自动映射上才是遇到鬼了) private Integer id; private String name; private Integer age; private String gender;

那么 就需要我们自定义结果集来进行属性和列的映射关系
id="selectById" resultMap="myDog"> select * from dog where id=#{qweqw}

在resultMap标签中还有俩个特殊的子标签association和collection
现在进行代码演示,association的用法
步骤:在Emp实体类中加入dept对象属性,那么在查询当前员工信息的时候并且查询到员工的部门信息
id="selectEmpAndDept" resultMap="empDept"> select * from emp e left join dept d on e.deptno = d.deptno where e.empno=#{empnoxx} id="selectEmpAndDept2" resultMap="empDept2"> select * from emp leftjoin dept on emp.deptno=dept.deptno where emp.empno=#{empno}

呼呼,下面开始collocation标签的用法
这里的步骤:在Dept表中加入Emp对象属性,采用一对多的关系,查询部门下所有员工信息以及部门信息
="selectDeptAndEmp" resultMap="DeptEmp"> select * from emp left join dept on dept.deptno=emp.deptno where dept.deptno=#{deptno}

分步查询 和关联查询结果一样,但是更加灵活。这给大家写个Mybatis中分步查询的案例
老规矩:需要以下食材:
1、实体类俩份,一份Emp,一份Dept
2、全局配置xml文件一份(上一篇有写)
3、接口俩个EmpDao和DeptDao
4、sql配置文件俩 EmpDao.xml文件和DeptDao.xml文件
起锅烧油:开始
菜系:查询Emp表中某员工信息并且附带此员工的部门信息
一:
在EmpDao接口中
//我先查出这个员工信息,因为员工信息是有部门编号的 public Emp selectByStep(Integer empno);

在DeptDao接口中

//既然是分步,那么这个dept的部门编号是从员工信息中获取的才是 public Dept selectDeptByStep(Integer deptno);

DeptDao.xml文件配置如下
id="selectDeptByStep" resultType="com.kaisi.bean.Dept"> select * from dept where deptno=#{deptno}

EmpDap.xml文件配置如下
id="selectByStep" resultMap="empStep"> select * from emp where empno=#{empno}

从下面结果就可以看出,我调用了一个接口方法,但是sql语句执行了俩条,并且把结果都组合成新的结果集并且返回。
这就是分步查询:好处:海量数据下表关联查询效率会降低,分步查询效率此时会高于表连接查询
但是在表中数据量比较小的情况下,关联查询和分步查询的效率就没有很大的区别了;
但是分步查询有个好处,就是可以延迟查询
MyBatis打工人——sql配置文件详解
文章图片

延迟查询 延迟查询的开启只需要再全局配置文件中加入
>name="mapUnderscoreToCamelCase" value="https://www.it610.com/article/true"/>name="lazyLoadingEnabled" value="https://www.it610.com/article/true"/>

分析结果:当开启懒加载后,我们在调用的时候只是使用了dept表的中的dname属性,并不需要emp表中的数据,那么减少数据库压力,当然是越少执行越好,这就是懒加载的好处。
MyBatis打工人——sql配置文件详解
文章图片

下面我把懒加载关闭,再看结果
>name="mapUnderscoreToCamelCase" value="https://www.it610.com/article/true"/>name="lazyLoadingEnabled" value="https://www.it610.com/article/false"/>

相同的调用,关闭懒加载却执行了分步查询的所有sql(是基于刚刚分步的基础上做的,俩俩配合使用奇妙的味道)
MyBatis打工人——sql配置文件详解
文章图片

    推荐阅读