目录
1.表关系映射到实体类中时,实体类如何处理对应的复杂的表的关系呢?
1. mybatis获取参数值的两种方式
1.${}:字符串拼接;在为字符串类型/日期类型赋值时需要手动加单引号
* 在底层解析时被视为一个字段
2.#{}:占位符赋值;在底层被解析时自动添加单引号
* 在底层解析时被视为一个问号❓
2.xml映射文件的常用标签
1.数据库操作标签
select、insert、update、delete
2.自定义映射处理标签:resultMap
3.sql片段标签:sql、include
4.自增主键标签:selectKey
5.动态sql标签:
if、where、trim、foreach,choose、when、otherwise
3.Dao接口是如何操作数据库的?
1.创建方式:MyBatis中,Dao接口中会写Mapper接口xxxMapper,对应在相同的文件路径下创建一个同名的xxxMapper.xml
2.关联方式:mapper接口xxxMapper和映射文件xxxMapper.xml要保证两个一致
1. mapper接口的全类名和映射文件的namespace一致
2. mapper接口中的方法的方法名要和映射文件中的SQL的ID保持一致
3.定位方式:调用mapper接口方法时,会根据 全类名.方法名 作为key,定位一个MappedStatement
4.代码示例:如调用UserMapper的insertUser()方法,会根据com.gz.java.mybatis.mapper.UserMapper.insertUser()定位到xml文件中namespace=com.gz.java.mybatis.mapper.UserMapper,id=insertUser的MappedStatement
public interface UserMapper {
int insertUser();
}
<mapper namespace="com.gz.java.mybatis.mapper.UserMapper">
<!--int insertUser();-->
<insert id="insertUser">
insert into t_user values(null,'admin','123456',23,'男','12345@qq.com')
</insert>
4.Dao接口的方法能够重载吗
可以;但是接口方法对应的映射文件中的id必须是唯一的
5.MyBatis动态sql
1.作用:根据特定条件动态拼装SQL语句的功能,存在的意义是为了解决拼接SQL语句字符串时的问题
2.动态sql使用的标签:
* 第一个标签:if:通过test属性中的表达式判断标签中的内容是否有效(是否会拼接到SQL中)
* 第二个标签:where:(与if结合使用)
* 第一个功能:若where标签中有表达式成立,则自动生成where
* 第二个功能:能将内容中前面多余的and去掉,但是内容后面的and无法去掉
* 第三个功能:若where标签中的表达式都不成立,则where标签没有任何功能
* 第三个标签:trim:用来截取条件中的内容;具有四个标签
* prefix,suffix:在标签中内容的前面或后面添加指定内容
* prefixOverrides,suffixOverrides:在标签中内容前面或后面去掉指定内容
* 第四组标签:foreach(极其重要,掌握);可以实现批量添加和批量删除(三种方法),共有五个属性
* collection:设置要循环的数组或集合
* item:用一个字符串表示数组或集合中的每一个数据
* separator:设置每次循环的数据之间的分隔符
* open:循环的所有内容以什么开始
* close:循环的所有内容以什么结束
* 第五个标签:choose,when,otherwise:相当于:if-else if-else(用的不多)
* when至少设置一个;otherwise至多设置一个
* 第六个标签:sql片段:可以记录一段sql,在需要使用的地方使用include标签进行引用
详细使用方式请参考:
MyBatis的重点知识_perseveregz的博客-CSDN博客
6.MyBatis中实现分页功能
1.分页的实现:
sql中使用limit实现分页功能
使用分页插件实现分页功能
2.分页插件的实现原理
使用MyBatis提供的插件接口,在插件的拦截方法内拦截待执行的sql语句,然后重写sql,添加对应的物理分页语句和物理分页参数
7.MyBatis的映射形式
1.将字段名设置别名
如果别名和属性名相等就可以成功输出值,否则不一致的名字输出将为null
<!--Emp getEmpByEmpId(@Param("empId”) Integer empId);-->
<select id="getEmpByEmpId” resultType="Emp">
select emp_id empId,emp_name empName,age,gender from t_emp where emp_id = #{empId}
</select>
2. 使用resultMap自定义映射处理
* id:唯一标识
* type:处理映射关系的实体类的类型
<!-- Dept getDeptAndEmpByStepOne(@Param("deptId") Integer deptId); -->
<resultMap id="getDeptAndEmpByStepOne" type="Dept">
<id column="dept_id" property="deptId"></id>
<result column="dept_name" property="deptName"></result>
</resultMap>
<select id="getDeptAndEmpByStepOne" resultMap="getDeptAndEmpByStepOne">
select * from t_dept where dept_id = #{deptId}
</select>
映射关系确定后,MyBatis通过反射创建对象,并为对象属性赋值。
8.MyBatis实现多对一的映射关系
第一种方法:级联方式处理
<!-- 处理多对一映射关系的三种方法 -->
<!-- Emp getEmpAndDeptByEmpId(@Param("id")Integer id); -->
<!-- 第一种方法:级联方式处理 -->
<resultMap id="getEmpAndDeptResultMap" type="Emp">
<id column="emp_id" property="empId"></id>
<result column="emp_name" property="empName"></result>
<result column="age" property="age"></result>
<result column="gender" property="gender"></result>
<result column="dept_id" property="dept.deptId"></result>
<result column="dept_name" property="dept.deptName"></result>
</resultMap>
<select id="getEmpAndDeptByEmpId" resultMap="getEmpAndDeptResultMap">
SELECT *
FROM t_emp
LEFT JOIN t_dept
ON t_emp.dept_id = t_dept.dept_id
WHERE t_emp.emp_id = #{empId};
</select>
第二种方法:association;专门用来处理多对一的映射关系(专门处理实体类类型的属性)
<!-- 第二种方法:association处理 -->
<resultMap id="getEmpAndDeptResultMap" type="Emp">
<id column="emp_id" property="empId"></id>
<result column="emp_name" property="empName"></result>
<result column="age" property="age"></result>
<result column="gender" property="gender"></result>
<association property="dept" javaType="Dept">
<id column="dept_id" property="deptId"></id>
<result column="dept_name" property="deptName"></result>
</association>
</resultMap>
<select id="getEmpAndDeptByEmpId" resultMap="getEmpAndDeptResultMap">
SELECT *
FROM t_emp
LEFT JOIN t_dept
ON t_emp.dept_id = t_dept.dept_id
WHERE t_emp.emp_id = #{empId};
</select>
第三种方法:分步查询
* 注意:此时应将分步查询的不同步骤写在对应的映射文件中
* select的唯一标识:namespace.SQL Id
/**
* 通过分步查询员工以及对应的部门信息的第一步
* @param empId
* @return
*/
Emp getEmpAndDeptByStepOne(@Param("empId") Integer empId);
/**
* 通过分步查询员工以及对应的部门信息的第二步
* @param deptId
* @return
*/
Dept getEmpAndDeptByStepTwo(@Param("deptId") Integer deptId);
<!-- 第三种方法:分步查询-->
<!-- Emp getEmpAndDeptByStepOne(@Param("empId") Integer empId);-->
<resultMap id="empAndDeptByStepResultMap" type="Emp">
<id column="emp_id" property="empId"></id>
<result column="emp_name" property="empName"></result>
<result column="age" property="age"></result>
<result column="gender" property="gender"></result>
<association property="dept" fetchType="lazy"
select="com.gz.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo"
column="dept_id"></association>
</resultMap>
<select id="getEmpAndDeptByStep" resultMap="empAndDeptByStepResultMap">
select * from t_emp where emp_id = #{empId}
</select>
<!-- Dept getEmpAndDeptByStepTwo(@Param("deptId") Integer deptId); -->
<select id="getEmpAndDeptByStepTwo" resultType="Dept">
select * from t_dept where dept_id = #{deptId}
</select>
9.MyBatis实现一对多的映射关系
1.表关系映射到实体类中时,实体类如何处理对应的复杂的表的关系呢?
* 对一,对应一个对象;对多,对应一个集合
* 比如,员工表和部门表;一个部门对应多个员工;若在查员工时要查部门,就是多对一,此时在员工实体类对象中写上一个部门对象;
* 若是查询一个部门的多个员工,就是一对多;在部门的实体类对象中为多个员工写一个list集合
public class Dept {
private Integer deptId;
private String deptName;
private List<Map> emps;
}
2.处理一对多的映射关系的方法
* 第一种方法:collection(也是一个模版)
<!--
2.处理一对多的映射关系的方法
第一种方法:collection(也是一个模版)
-->
<!-- Dept getDeptAndEmpByDeptId(@Param("deptId") Integer deptId); -->
<resultMap id="getDeptIdByRestultMap" type="Dept">
<id column="dept_id" property="deptId"></id>
<result column="dept_name" property="deptName"></result>
<collection property="emps" ofType="Emp">
<id column="emp_id" property="empId"></id>
<result column="emp_name" property="empName"></result>
<result column="age" property="age"></result>
<result column="gender" property="gender"></result>
</collection>
</resultMap>
<select id="getDeptAndEmpByDeptId" resultMap="getDeptIdByRestultMap">
select *
from t_dept
left join t_emp
on t_dept.dept_id = t_emp.dept_id
where t_dept.dept_id = #{deptId}
</select>
* 第二种方法:分步查询
<!-- 第二种方法:分步查询-->
<!-- Dept getDeptAndEmpByStepOne(@Param("deptId") Integer deptId); -->
<!-- 分步查询的第一步-->
<resultMap id="getDeptAndEmpByStepOne" type="Dept">
<id column="dept_id" property="deptId"></id>
<result column="dept_name" property="deptName"></result>
<collection property="emps"
select="com.gz.mybatis.mapper.EmpMapper.getDeptAndEmpByStepTwo"
column="dept_id"></collection>
</resultMap>
<select id="getDeptAndEmpByStepOne" resultMap="getDeptAndEmpByStepOne">
select * from t_dept where dept_id = #{deptId}
</select>
<!-- List<Emp> getDeptAndEmpByStepTwo(@Param("deptId") Integer deptId); -->
<select id="getDeptAndEmpByStepTwo" resultType="Emp">
select * from t_emp where dept_id = #{deptId}
</select>
10.分步查询的好处
1. 可以实现延迟加载
* 在分步查询中,可以先给出查询的第一步结果,第二步结果如果暂时不需要可以不给出。减少内存消耗
2.实现延迟加载
要实现延迟加载,必须先在核心配置文件中设置两个全局配置信息
* lazyLoadingEnabled:延迟加载的全局开关。开启后,所有关联对象都会延迟加载;默认为false
* aggressiveLazyLoading:开启时,任何方法的调用都会加载该对象的所有属性。否则,每个属性会按需加载;默认为true
<settings>
<!-- 开启延迟加载 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 按需加载 -->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
* 这两个方法可以实现按需加载,要获取的数据是什么,就执行相应的SQL。
3.在延迟加载时如何查询所有结果
此时存在一个问题,在核心配置文件中写了全局配置,会让所有分步查询都实现延迟加载。但无法根据需要一次将所有结果都查询出来
解决方法:在association中使用fetchType:在开启了延迟加载的环境中,通过该属性设置当前的分步查询是否使用延迟加载;
若为:"eager":立即加载
"lazy":延迟加载
<!-- fetchType = "eager"(立即加载)-->
<!-- fetchType = "lazy"(延迟加载)-->
<association property="dept" fetchType="lazy"
select="com.gz.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo"
column="dept_id"></association>
</resultMap>