7、特殊SQL的执行
7.1、模糊查询
/**
* 测试模糊查询
* @param mohu
* @return
*/
List<User> testMohu(@Param("mohu") String mohu);
<!--List<User> testMohu(@Param("mohu") String mohu);-->
<select id="testMohu" resultType="User">
<!--select * from t_user where username like '%${mohu}%'-->
<!--select * from t_user where username like concat('%',#{mohu},'%')-->
select * from t_user where username like "%"#{mohu}"%"
</select>
7.2、批量删除
/**
* 批量删除
* @param ids
* @return
*/
int deleteMore(@Param("ids") String ids);
<!--int deleteMore(@Param("ids") String ids);-->
<delete id="deleteMore">
delete from t_user where id in (${ids})
</delete>
7.3、动态设置表名
/**
* 动态设置表名,查询所有的用户信息
* @param tableName
* @return
*/
List<User> getAllUser(@Param("tableName") String tableName);
<!--List<User> getAllUser(@Param("tableName") String tableName);-->
<select id="getAllUser" resultType="User">
select * from ${tableName}
</select>
7.4、添加功能获取自增的主键
- 场景模拟:
- t_clazz(clazz_id,clazz_name)
- t_student(student_id,student_name,clazz_id)
- 1、添加班级信息
- 2、获取新添加的班级的id
- 3、为班级分配学生,即将某学的班级id修改为新添加的班级的id
/**
* 添加用户信息
* @param user
* @return
* useGeneratedKeys:设置使用自增的主键
* keyProperty:因为增删改有统一的返回值是受影响的行数,因此只能将获取的自增的主键放在传输的参
数user对象的某个属性中
*/
int insertUser(User user);
<!--int insertUser(User user);-->
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
insert into t_user values(null,#{username},#{password},#{age},#{sex})
</insert>
8、自定义映射resultMap
8.1、resultMap处理字段和属性的映射关系
8.1.1、三种方式
对于字段名和属性名不一致的情况,如何处理映射关系
1、为查询的字段设置别名,和属性名保持一致 (一般不用)
2、当字段符合mysql的要求使用_,而属性符合java要求使用驼峰
- 此时可以在mybatis的核心配置文件中设置一个全局配置
- 可以自动将下划线映射为驼峰
- emp_id:empId,emp_name:empName
<!--设置将下划线映射为驼峰-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
- 3、使用resultMap自定义处理映射
- resultMap:
- resultMap:自定义的映射关系
- id:唯一标识
- type:处理映射关系的实体类的类型
- 使用了resultMap就需要把每个映射关系都写出来
- 常用的标签:
- id:处理主键和实体类中属性的映射关系
- result:处理普通字段和实体类中属性的映射关系
- association:处理多对一的映射关系(处理实体类类型的属性)
- column:设置映射关系中的字段名,必须是SQL查询出的某个字段
- property:设置映射关系中的属性的属性名,必须是处理的实体类类型中的属性名
//测试处理字段和属性名不一致情况下的映射关系
Emp getEmpByEmpId(@Param("empId") Integer empId);
<!--Emp getEmpByEmpId(@Param("empId") Integer empId);-->
<!--
处理字段名和属性名不一致的情况,如何处理映射关系
1、为查询的字段设置别名,和属性名保持一致 (一般不用)
2、当字段符合mysql的要求使用_,而属性符合java要求使用驼峰
此时可以在mybatis的核心配置文件中设置一个全局配置,
可以自动将下划线映射为驼峰
emp_id:empId,emp_name:empName
3、使用resultMap自定义处理映射
-->
<!--
resultMap:自定义的映射关系
id:唯一标识
type:处理映射关系的实体类的类型
使用了resultMap就需要把每个映射关系都写出来
常用的标签:
id:处理主键和实体类中属性的映射关系
result:处理普通字段和实体类中属性的映射关系
association:处理多对一的映射关系(处理实体类类型的属性)
column:设置映射关系中的字段名,必须是SQL查询出的某个字段
property:设置映射关系中的属性的属性名,必须是处理的实体类类型中的属性名
-->
<resultMap id="empResultMap" type="Emp">
<id column="emp_id" property="empId"/>
<result column="emp_name" property="empName"/>
<result column="age" property="age"/>
<result column="gender" property="gender"/>
</resultMap>
<select id="getEmpByEmpId" resultMap="empResultMap">
select * from t_emp where emp_id = #{empId}
</select>
<select id="getEmpByEmpIdOld" resultType="Emp">
select * from t_emp where emp_id = #{empId}
</select>
8.2、多对一映射处理
- 场景模拟:查询员工信息以及员工所对应的部门信息
- 一个部门对应着多个员工,要查询完整的员工信息,就需要根据数据库中员工所在部门的部门id查询到对应的部门信息。
8.2.1、级联方式处理映射关系
<resultMap id="empDeptMap" type="Emp">
<id column="eid" property="eid"></id>
<result column="ename" property="ename"></result>
<result column="age" property="age"></result>
<result column="sex" property="sex"></result>
<result column="did" property="dept.did"></result>
<result column="dname" property="dept.dname"></result>
</resultMap>
<!--Emp getEmpAndDeptByEid(@Param("eid") int eid);-->
<select id="getEmpAndDeptByEid" resultMap="empDeptMap">
select emp.*,dept.* from t_emp emp left join t_dept dept on emp.did =
dept.did where emp.eid = #{eid}
</select>
8.2.2、使用association处理映射关系
<resultMap id="empAndDeptResultMap" type="Emp">
<id column="emp_id" property="empId"/>
<result column="emp_name" property="empName"/>
<result column="age" property="age"/>
<result column="gender" property="gender"/>
<!--
association:处理实体类类型的属性
property:设置需要处理映射关系的属性的属性名
JavaType:表示要处理属性的类型,使用别名
-->
<association property="dept" javaType="Dept">
<id column="dept_id" property="deptId"/>
<result column="dept_name" property="deptName"/>
</association>
</resultMap>
<!--Emp getEmpAndDeptByEmpId(@Param("empId") Integer empId);-->
<select id="getEmpAndDeptByEmpId" resultMap="empAndDeptResultMap">
select *
from t_emp
left join t_dept on t_emp.dept_id = t_dept.dept_id
where emp_id = #{empId}
</select>
8.2.3、分步查询
//通过分步查询获取员工和部门的信息第一步
Emp getEmpAndDeptByStepOne(@Param("empId") Integer empId);
//通过分步查询获取员工和部门的信息第二步,查询部门信息
Dept getEmpAndDeptByStepTwo(@Param("deptId")Integer deptId);
<resultMap id="empAndDeptByStepResultMap" type="Emp">
<id column="emp_id" property="empId"/>
<result column="emp_name" property="empName"/>
<result column="age" property="age"/>
<result column="gender" property="gender"/>
<!--
fetchType:在开启延迟加载的环境中,指定当前的sql是延迟加载还是立即加载
eager表示立即加载,lazy表示懒加载
property:设置需要处理映射关系的属性的属性名
select:设置分步查询的SQL的唯一标识
column:将查询出来的某个字段作为分布查询的SQL条件
-->
<association fetchType="eager"
property="dept"
select="com.zylai.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo"
column="dept_id">
</association>
</resultMap>
<!--Emp getEmpAndDeptByStepOne(@Param("empId") Integer empId);-->
<select id="getEmpAndDeptByStepOne" resultMap="empAndDeptByStepResultMap">
select * from t_emp where emp_id = #{empId}
</select>
8.2.4、延迟加载
- 在核心配置文件中配置
<!--开启延迟加载
对于分步查询,关联的对象将会延迟加载。
比如获取emp信息,如果只是打印emp.getEmpName(),用不到Dept的信息
那么查询Dept的第二步将不会执行。
-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--value为false时按需加载-->
<setting name="aggressiveLazyLoading" value="false"/>
- 开启之后还可以在mapper映射文件特定sql中的association标签的fetchType属性选择是立即加载还是延迟加载
8.3、一对多映射处理
8.3.1、collection
- collection标签表示一端中的集合,标签的ofType属性指定集合中的类型
/**
* 根据部门id查新部门以及部门中的员工信息
* @param did
* @return
*/
Dept getDeptEmpByDid(@Param("did") int did);
<resultMap id="deptEmpMap" type="Dept">
<id property="did" column="did"></id>
<result property="dname" column="dname"></result>
<!--
ofType:设置collection标签所处理的集合属性中存储数据的类型
-->
<collection property="emps" ofType="Emp">
<id property="eid" column="eid"></id>
<result property="ename" column="ename"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
</collection>
</resultMap>
<!--Dept getDeptEmpByDid(@Param("did") int did);-->
<select id="getDeptEmpByDid" resultMap="deptEmpMap">
select dept.*,emp.* from t_dept dept left join t_emp emp on dept.did =
emp.did where dept.did = #{did}
</select>
8.3.2、分步查询
- 1、 查询部门信息
/**
* 分步查询部门和部门中的员工
* @param did
* @return
*/
Dept getDeptByStep(@Param("did") int did);
<resultMap id="deptEmpStep" type="Dept">
<id property="did" column="did"></id>
<result property="dname" column="dname"></result>
<collection property="emps" fetchType="eager"
select="com.atguigu.MyBatis.mapper.EmpMapper.getEmpListByDid" column="did">
</collection>
</resultMap>
<!--Dept getDeptByStep(@Param("did") int did);-->
<select id="getDeptByStep" resultMap="deptEmpStep">
select * from t_dept where did = #{did}
</select>
- 2、根据部门id查询部门里的所有员工
/**
* 根据部门id查询员工信息
* @param did
* @return
*/
List<Emp> getEmpListByDid(@Param("did") int did);
<!--List<Emp> getEmpListByDid(@Param("did") int did);-->
<select id="getEmpListByDid" resultType="Emp">
select * from t_emp where did = #{did}
</select>
- 分步查询的优点:可以实现延迟加载
- 但是必须在核心配置文件中设置全局配置信息:
- lazyLoadingEnabled:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载
- aggressiveLazyLoading:当开启时,任何方法的调用都会加载该对象的所有属性。否则,每个属 性会按需加载
- 此时就可以实现按需加载,获取的数据是什么,就只会执行相应的sql。此时可通过association和 collection中的fetchType属性设置当前的分步查询是否使用延迟加载, fetchType="lazy(延迟加 载)|eager(立即加载)"