这一篇,老多代码了,我的天。我用了经典的emp表和dept表做演示。加油!打工人。(看到隔壁的铁人为了调休奋战了36小时没睡,我陷入入了沉思)
在SQL映射文件中,有需要的顶级元素标签:
--cache – 该命名空间的缓存配置。
--cache-ref – 引用其它命名空间的缓存配置。
--resultMap – 描述如何从数据库结果集中加载对象,是最复杂也是最强大的元素。
--parameterMap – 老式风格的参数映射。此元素已被废弃,并可能在将来被移除!请使用行内参数映射。文档中不会介绍此元素。
--sql – 可被其它语句引用的可重用语句块。
--insert – 映射插入语句。
--update – 映射更新语句。
--delete – 映射删除语句。
--select – 映射查询语句。
并且在每个顶级元素标签里,是能添加很多数据的。当然了,常用就那么几个
属性 | 描述 |
---|---|
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 id="insertUser" useGeneratedKeys="true" keyProperty="id">
insert into user(id,uname,age,gender,hobby) values (#{id},#{uname},#{age},#{gender},#{hobby})
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>
这个元素是相当的麻烦,麻烦就麻烦这个顶级元素上了。秀到飞起
1、当查询语句的时候,一般我们都会动态的将属性添加到sql语句中,在Mybatis中当然也一样了
<select id="selectEmpById" resultType="com.kaisi.bean.Emp">
select * from emp where empno = #{qwer}
select>
为什么引用数据类型就不行了呢?
/*
在Emp的接口中,我也是根据empno进行查询对象,但是我单参数传入的却是一个对象
(可以确定是引用类型对吧!)
那么在sql映射的配置文件 EmpDao.xml中对应的sql语句是否可以#{jqk或qwe}随便写?
测试就会发现,不能了,因为当参数为一个对象的时候,是根据具体的属性名来确定从对象中的那个属性来取到需要数值
*/
public Emp selectByEmp(Emp emp);
xml文件sql如下
<select id="selectByEmp" resultType="com.kaisi.bean.Emp">
select * from emp where empno = #{empno}
select>
在SQL映射文件中单参数验证完毕后,就需要验证多参数传递了
//接口定义,多参数
public Emp selectByBoth(Integer empno,Double sal);
<select id="selectByBoth" resultType="com.kaisi.bean.Emp">
select * from emp where empno=#{arg0} and sal>#{arg1}
select>
当然了,你如果觉得上面这种arg或者param比较low,你也可以用注解的形式
public Emp selectByBoth(@Param("empno") Integer empno,@Param("sal") Double sal);
在xml中我们是有俩种取值方式的一种是${}一种是#{}
<select id="selectEmpByNoAndName" resultType="com.kaisi.bean.Emp">
select * from ${t} where empno=#{empno} and ename=${ename}
select>
当出现数据库表字段与实体类的属性不不应的时候,是无法直接进行映射的,那么就需要自定义结果集了
//在Java中我定义的属性却是没有d开头的(能自动映射上才是遇到鬼了)
private Integer id;
private String name;
private Integer age;
private String gender;
那么 就需要我们自定义结果集来进行属性和列的映射关系
<mapper namespace="com.kaisi.dao.DogDao">
<resultMap id="myDog" type="com.kaisi.bean.Dog">
<id property="id" column="id">id>
<result property="name" column="dname">result>
<result property="age" column="dage">result>
<result property="gender" column="dgender">result>
resultMap>
<select id="selectById" resultMap="myDog">
select * from dog where id=#{qweqw}
select>
mapper>
在resultMap标签中还有俩个特殊的子标签association和collection
现在进行代码演示,association的用法
步骤:在Emp实体类中加入dept对象属性,那么在查询当前员工信息的时候并且查询到员工的部门信息
<resultMap id="empDept" type="com.kaisi.bean.Emp">
<id column="empno" property="empno">id>
<result column="ename" property="ename">result>
<result column="job" property="job">result>
<result column="mgr" property="mgr">result>
<result column="hiredate" property="hiredate">result>
<result column="sal" property="sal">result>
<result column="comm" property="common">result>
<result column="deptno" property="dept.deptno">result>
<result column="dname" property="dept.dname">result>
<result column="loc" property="dept.loc">result>
resultMap>
<select id="selectEmpAndDept" resultMap="empDept">
select * from emp e left join dept d on e.deptno = d.deptno where e.empno=#{empnoxx}
select>
<resultMap id="empDept2" type="com.kaisi.bean.Emp">
<id column="empno" property="empno">id>
<result column="ename" property="ename">result>
<result column="job" property="job">result>
<result column="mgr" property="mgr">result>
<result column="hiredate" property="hiredate">result>
<result column="sal" property="sal">result>
<result column="comm" property="common">result>
<result column="deptno" property="deptno">result>
<association property="dept" javaType="com.kaisi.bean.Dept">
<id column="deptno" property="deptno">id>
<result column="loc" property="loc">result>
<result column="dname" property="dname">result>
association>
resultMap>
<select id="selectEmpAndDept2" resultMap="empDept2">
select * from emp left join dept on emp.deptno=dept.deptno where emp.empno=#{empno}
select>
呼呼,下面开始collocation标签的用法
这里的步骤:在Dept表中加入Emp对象属性,采用一对多的关系,查询部门下所有员工信息以及部门信息
<!--
开始进行一对多的表与属性映射:也就是将从数据库中查到的数据一一映射到实体类中
唉西;这种一对多,演示中,一个部门会有多个员工,那么就需要另一个标签,collection。用于
在collection标签中,有一个ofType属性:指定集合中的元素类型
-->
<resultMap id="DeptEmp" type="com.kaisi.bean.Dept">
<id property="deptno" column="deptno"></id>
<result property="dname" column="dname"></result>
<result property="loc" column="loc"></result>
<collection property="emps" ofType="com.kaisi.bean.Emp">
<id column="empno" property="empno"></id>
<result column="ename" property="ename"></result>
<result column="job" property="job"></result>
<result column="mgr" property="mgr"></result>
<result column="hiredate" property="hiredate"></result>
<result column="sal" property="sal"></result>
<result column="comm" property="common"></result>
<result column="deptno" property="deptno"></result>
</collection>
</resultMap>
<select id="selectDeptAndEmp" resultMap="DeptEmp">
select * from emp left join dept on dept.deptno=emp.deptno where dept.deptno=#{deptno}
</select>
和关联查询结果一样,但是更加灵活。这给大家写个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文件配置如下
<select id="selectDeptByStep" resultType="com.kaisi.bean.Dept">
select * from dept where deptno=#{deptno}
select>
EmpDap.xml文件配置如下
<resultMap id="empStep" type="com.kaisi.bean.Emp">
<id column="empno" property="empno">id>
<result column="ename" property="ename">result>
<result column="job" property="job">result>
<result column="mgr" property="mgr">result>
<result column="hiredate" property="hiredate">result>
<result column="sal" property="sal">result>
<result column="comm" property="comm">result>
<result column="deptno" property="deptno">result>
<association property="dept" select="com.kaisi.dao.DeptDao.selectDeptByStep" column="deptno">association>
resultMap>
<select id="selectByStep" resultMap="empStep">
select * from emp where empno=#{empno}
select>
从下面结果就可以看出,我调用了一个接口方法,但是sql语句执行了俩条,并且把结果都组合成新的结果集并且返回。
这就是分步查询:好处:海量数据下表关联查询效率会降低,分步查询效率此时会高于表连接查询
但是在表中数据量比较小的情况下,关联查询和分步查询的效率就没有很大的区别了;
但是分步查询有个好处,就是可以延迟查询
延迟查询的开启只需要再全局配置文件中加入
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
settings>
分析结果:当开启懒加载后,我们在调用的时候只是使用了dept表的中的dname属性,并不需要emp表中的数据,那么减少数据库压力,当然是越少执行越好,这就是懒加载的好处。
下面我把懒加载关闭,再看结果
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
<setting name="lazyLoadingEnabled" value="false"/>
settings>