一,解决数据表中字段名和实体类属性名不一致的的情况
a>为字段名起别名,保持字段名和属性名一致,如数据表中字段名为emp_name,实体类中属性名为
empName,mybatis在查询出结果后发现字段名和属性名不一致时,就无法为属性赋值
<select id="getAllEmp" resultType="Emp">
select eid,emp_name empName,age,sex,email from t_emp
</select>
b>设置全局配置,将_自动映射为驼峰
在mybatis核心配置文件中设置全局配置可以也可以解决字段名和属性名不一致的问题,
<!--设置全局配置,将字段名的下划线自动映射为驼峰 -->
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
mapUnderscoreToCamelCase默认值为false,需要手动设置为true,映射需要符合一定规则,如
emp_name会映射成empName
c>使用自定义映射resultMap
resultMap id="empResultMap" type="Emp">
<id property="eid" column="eid"></id>
<result property="empName" column="emp_name"></result>
<result property="age" column="age"></result>zi
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
</resultMap>
<select id="getAllEmp" resultMap="empResultMap">
<!--select eid,emp_name empName,age,sex,email from t_emp -->
select * from t_emp
</select>
resultMap标签
id:唯一标识 type:设置映射关系中的实体类类型
子标签
id: 设置主键的元素关系 result:设置普通字段的映射关系 property:设置映射关系中的属性名,必须
是type属性所设置的实体类类型中的属性名 colum:设置映射关系的字段名,必须是sql语句查询出的
字段名
二,处理多对一的映射关系
如有员工表和部门表,员工表中存有部门表的did字段,
现要根据员工id查询出员工信息和所在的部门信息,这就属于多对一的关系yao
a>级联属性赋值,使用resultMap自定义关系映射
<resultMap id="getEmpAndDeptResultMap" type="Emp">
<id property="eid" column="eid"></id>
<result property="empName" column="emp_name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
<result property="dept.did" column="did"></result>
<result property="dept.deptName" column="dept_name"></result>
</resultMap>
<select id="getEmpAndDept" resultMap="getEmpAndDeptResultMap">
select * from t_emp left join t_dept on t_emp.did=t_dept.did where t_emp.eid=#{eid}
</select>
b>使用assocation标签
<resultMap id="getEmpAndDeptResultMapOne" type="Emp">
<id property="eid" column="eid"></id>
<result property="empName" column="emp_name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
<association property="dept" javaType="Dept">
<id property="did" column="did"></id>
<result property="deptName" column="dept_name"></result>
</association>
</resultMap>
<select id="getEmpAndDept" resultMap="getEmpAndDeptResultMapOne">
select * from t_emp left join t_dept on t_emp.did=t_dept.did where t_emp.eid=#{eid}
</select>
association标签:处理多对一的映射关系
property:需要处理多对的映射关系的属性名
javaType:该属性的实体类类型
c>通过分布查询
所谓分布查询,就是不用级联查询,分别用两个sql语句单独查询,如现要根据员工id查询出员工信息和
所在的部门信息,就需要分两步查询,第一步根据eid查询出员工信息的did,第二步就是根据did查询出
相关的部门信息
/* Emp的Mapper接口定义的方法
分布查询的第一步:查询员工信息
*/
Emp getEmpAndDeptByStepOne(@Param("eid") Integer eid);
EmpMapper接口的映射文件,注意还是需要使用到association标签,但与第二种方式不同的是,这种
方式关联着另一个SQL语句,property:需要处理多对映射关系的属性名 select:设置分布查询的sql的
唯一标识(namespace.sqlid或者另一个sql语句的mapper接口的全类名.方法名)column:设置分布
查询的条件,在这个案例中条件为did
<!-- Emp getEmpAndDeptByStepOne();-->
<resultMap id="getEmpAndDeptByStepOne" type="Emp">
<id property="eid" column="eid"></id>
<result property="empName" column="emp_name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
<association property="dept"
select="com.yhg.mapper.DeptMapper.getDeptByStepTwo"
column="did"></association>
</resultMap>
<select id="getEmpAndDeptByStepOne" resultMap="getEmpAndDeptByStepOne">
select * from t_emp where eid=#{eid}
</select>
分布查询的第二步,根据第一步查询的did的值查询出相应的部门信息
/*
分布查询的第二步:通过did查询员工所对应的部门
*/
Dept getDeptByStepTwo(@Param("did") Integer did);
<resultMap id="getEmpAndDeptByStepTwo" type="Dept">
<id property="did" column="did"></id>
<result property="deptName" column="dept_name"></result>
</resultMap>
<select id="getDeptByStepTwo" resultMap="getEmpAndDeptByStepTwo">
select * from t_dept where did=#{did}
</select>
三,延迟加载
延迟加载也叫懒加载,按需加载,当需要使用到的数据时,才去执行查询加载
全局配置文件开启延迟加载开关
案例一:还是按照分布查询的那个方法,当我们开启了延迟加载后,我们去访问员工姓名时,会发现log4日
志显示只执行了第一步的sql语句
DEBUG 02-06 09:07:20,857 ==> Preparing: select * from t_emp where eid=? (BaseJdbcLogger.java:137)
DEBUG 02-06 09:07:21,039 ==> Parameters: 3(Integer) (BaseJdbcLogger.java:137)
DEBUG 02-06 09:07:21,357 <== Total: 1 (BaseJdbcLogger.java:137)
王五
当我们关闭延迟加载后,会发现执行了两个sql语句,把员工所在的部门全部查询出来了
DEBUG 02-06 09:10:39,715 ==> Preparing: select * from t_emp where eid=? (BaseJdbcLogger.java:137)
DEBUG 02-06 09:10:39,793 ==> Parameters: 3(Integer) (BaseJdbcLogger.java:137)
DEBUG 02-06 09:10:39,844 ====> Preparing: select * from t_dept where did=? (BaseJdbcLogger.java:137)
DEBUG 02-06 09:10:39,845 ====> Parameters: 3(Integer) (BaseJdbcLogger.java:137)
DEBUG 02-06 09:10:39,850 <==== Total: 1 (BaseJdbcLogger.java:137)
DEBUG 02-06 09:10:39,851 <== Total: 1 (BaseJdbcLogger.java:137)
王五
案例二:还是按照分布查询的那个方法,现在开启延迟加载后,我们再访问部门信息,中间以
++++++++作为分割符,会发现,我们先访问的是员工名,后访问的部门信息,可以看到结果是我们访问员
工名,就查询员工名,访问部门信息就查询部门信息,按照我们的需要来查询
DEBUG 02-06 09:14:50,489 ==> Preparing: select * from t_emp where eid=? (BaseJdbcLogger.java:137)
DEBUG 02-06 09:14:50,571 ==> Parameters: 3(Integer) (BaseJdbcLogger.java:137)
DEBUG 02-06 09:14:50,734 <== Total: 1 (BaseJdbcLogger.java:137)
王五
+++++++++++
DEBUG 02-06 09:14:50,736 ==> Preparing: select * from t_dept where did=? (BaseJdbcLogger.java:137)
DEBUG 02-06 09:14:50,737 ==> Parameters: 3(Integer) (BaseJdbcLogger.java:137)
DEBUG 02-06 09:14:50,740 <== Total: 1 (BaseJdbcLogger.java:137)
Dept{did=3, deptName='C'}
但是当我们关闭延迟加载时,会发现sql语句是一起执行的,
DEBUG 02-06 09:17:50,013 ==> Preparing: select * from t_emp where eid=? (BaseJdbcLogger.java:137)
DEBUG 02-06 09:17:50,108 ==> Parameters: 3(Integer) (BaseJdbcLogger.java:137)
DEBUG 02-06 09:17:50,158 ====> Preparing: select * from t_dept where did=? (BaseJdbcLogger.java:137)
DEBUG 02-06 09:17:50,159 ====> Parameters: 3(Integer) (BaseJdbcLogger.java:137)
DEBUG 02-06 09:17:50,163 <==== Total: 1 (BaseJdbcLogger.java:137)
DEBUG 02-06 09:17:50,165 <== Total: 1 (BaseJdbcLogger.java:137)
王五
+++++++++++
Dept{did=3, deptName='C'}
开启了延迟加载后,所有的分布查询都会延迟加载,但是对于特殊分布查询想不开启延迟加载,要想是
延迟加载变得可控,association标签中有一个属性fetchType:eage(立即加载)|lazy(延迟加载),
四,处理一对多的映射关系
还是员工表和部门表,如果我们根据部门did查询出该部门下的所有员工信息时,这种情况属于是多对一
的关系,我们在处理一对多时,在实体类中定义了对象,但是在处理多对一时我们要在实体类中定义list集
合
a>通过collection标签
<resultMap id="getDeptAndEmp" type="Dept">
<id property="did" column="did"></id>
<result property="deptName" column="dept_name"></result>
<collection property="emps" ofType="Emp">
<id property="eid" column="eid"></id>
<result property="empName" column="emp_name"></result>
<result property="sex" column="sex"></result>
<result property="age" column="age"></result>
<result property="email" column="email"></result>
</collection>
</resultMap>
<select id="getDeptAndEmp" resultMap="getDeptAndEmp">
select * from t_dept left join t_emp on t_dept.did=t_emp.did where t_dept.did=#{did}
</select>
collection标签是用来处理一对多的映射关系
property设置多对一的属性名
ofType表示该属性所对应的集合中存储的数据的类型
b>分布查询
多对一的分布查询和一对多的分布查询类似
第一步:根据部门did查询部门信息,
<resultMap id="getDeptAndEmpByStepOne" type="Dept">
<id property="did" column="did"></id>
<result property="deptName" column="dept_name"></result>
<collection property="emps"
select="com.yhg.mapper.EmpMapper.getDeptAndEmpByStepTwo"
column="did"></collection>
</resultMap>
<select id="getDeptAndEmpBystepTwo" resultMap="getDeptAndEmpByStepOne">
select * from t_dept where did=#{did}
</select>
同样要使用collection标签,但里面的参数设置不一样,property:设置多对一的属性名。select:设置分布查询的sql的唯一标识(namespace.sqlid或者另一个sql语句的mapper接口的全类名.方法名)column:设置分布查询的条件,在这个案例中条件为did
第二步:根据did查询出所有员工信息
<resultMap id="getDeptAndEmpByStepTwo" type="Emp">
<id property="eid" column="eid"></id>
<result property="empName" column="emp_name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
</resultMap>
<select id="getDeptAndEmpByStepTwo" resultMap="getDeptAndEmpByStepTwo">
select * from t_emp where did=#{did}
</select>
需要注意的是多对一的分布查询也可以开启延迟加载。