明哥复习Mybatis(2)
不是原创,整理尚硅谷的内容得到的
六、自定义映射ResultMap
①处理字段和属性名不一致的情况
处理字段名和属性名不一致的方式一:为表中字段增加别名:
select emp_id empId,emp_name empName,age,gender from t_emp where emp_id=#{empId}
注意,表中没有empId和empName两个字段,MyBatis是根据查询结果的字段名为属性名赋值,这边字段名和属性名不一致,肯定是对应不上的。
方式二:设置一个全局配置
在全局配置中设置标签:
<setting name="mapUnderscoreToCamelCase" value="true"/>
这个标签必须要求符合MySQL和java命名规范才可以继续,Mybatis中的核心配置文件中设置一个全局配置,自动将下划线转化为驼峰
方式三:使用resultMap进行操作
<resultMap id="EmpAndDept" 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> </resultMap>
最上面id表示这个标签的唯一标识(这个id要和sql语句进行关联),type表示要处理的实体类
result处理普通字段和实体类对应关系
id用于处理主键
②处理多对一的映射关系(主要有三种方式):
方式一:多表联查,也就是用级联的方式,这时也是设置一个ResultMap就可以了,具体看下面这段代码:
<resultMap id="EmpAndDept" 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="getEmpAndDeptByEmpIdOne" resultMap="EmpAndDept">select t_emp.*,t_dept.*from t_empleft join t_depton t_emp.dept_id = t_dept.dept_idwhere t_emp.emp_id=#{empId} </select>
现在要通过员工id获取员工部门id和员工的全部信息,这时典型的多对一(多个员工对应一个部门),那么要在员工信息里面多一个属性(这个属性就是部门),这个时候MyBatis进行查询的时候,对于查询的结果dept_id和dept_name,由于我们在员工类中没有这两个属性,因此没有办法进行赋值,于是要用resultMap进行对应。
方式二:使用association处理映射关系
<resultMap id="empAndDeptResultMap" 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><id column="dept_name" property="deptName"></id></association> </resultMap>
标签property是用来表示要处理的属性,而javaType是设置要处理的属性的类型,这里本该写全类名,但是由于我在核心配置文件中为类型起了别名,所以可以这样写。
方式三:分布查询,写成两个sql语句
查询一:
<resultMap id="empAndDeptByStepResultResultMap" 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.atguigu.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo"column="dept_id"></association></resultMap><select id="getEmpAndDeptByStepOne" resultMap="empAndDeptByStepResultResultMap">select *from t_emp where emp_id=#{empId}</select>
查询二:
<select id="getEmpAndDeptByStepTwo" resultType="Dept">select *from t_dept where dept_id=#{deptId} </select>
说白了就是查两次,第一次查询部门id,第二次用查到的部门id去查询部门的信息;
这时association标签中字段有下面的含义:
Properties表示设置需要处理映射关系的属性的属性名
select表示我要跳转到哪个sql语句,注意这边(namespace+sql的id构成sql的唯一标识,也就是Mapper接口的抽象方法的全类名)
column表示将sql查询结果的某个字段作为分步查询的条件
这种方法单独有优势:
可以实现懒加载,也就是如果我单独只要获取员工姓名,那么也就不需要进行加载dept的信息了,此时只需要(核心)配置下面两个标签就可以了,也可以通过上面所描述的fetchType="lazy"标签来进行处理。
<!--延迟加载全局开关--><setting name="lazyLoadingEnabled" value="true"/> <!-- aggressiveLazyLoading 当开启时,任何sql查询的加载会导致所有属性的加载 --><setting name="aggressiveLazyLoading" value="false"/>
③处理一对多的映射关系
下面要查询一个部门里面的所有员工信息,那么要为部门类添加一个list这个属性,为这个属性加上泛型:员工。这时候只有两种处理方式:多步查询和collection。
方式一:使用Collection进行处理
<resultMap id="DeptAndEmpResultMap" 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>
<!-- 要处理的是Dept,因为Dept中有一个属性找不到映射关系,这边是处理映射关系的,所以Type是dept-->
ofType用于处理表与集合的映射关系,下面就和Collection是一样的了。
方式二:使用多步查询
先查询部门id,再根据部门id查询员工信息
两个接口分别如下:
Dept getDeptAndEmpByStepOne(@Param("deptId") Integer deptId); List<Emp> getDeptAndEmpByStepTwo(@Param("deptId") Integer deptId);
对应的映射文件如下
resultMap id="DeptAndEmpByStepOne" type="Dept"><id column="dept_id" property="deptId"></id><result column="dept_name" property="deptName"></result><collection property="emps"select="com.atguigu.mybatis.mapper.EmpMapper.getDeptAndEmpByStepTwo"column="dept_id"> <!--以dept_id为条件,我们是先查询部门的dept_id再根据部门的dept_id查询我要的emp的信息--></collection></resultMap><select id="getDeptAndEmpByStepOne" resultMap="DeptAndEmpByStepOne">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>
这个没有什么创新,和前面也大同小异
七、动态sql
动态sql就是几个标签
标签一:if标签
if标签:通过if判断标签中的内容是否有效,即标签中的内容是否会拼接到SQL中
比方说,服务器获取到信息后,如果得到的是空表示初始状态,如果获取的是空字符串表示客户没有填写信息,那么通过if标签可以判断是不是要将获取的信息拼接到sql语句当中,比如说:
<!-- List<Emp> getEmpByCondition(Emp emp);根据条件查询员工信息--><select id="getEmpByConditionOne" resultType="Emp">select * from t_emp where <if test="empName!=null and empName != ''">语句emp_name = #{empName}</if><if test="age!=null and age !=''"> <!-- 目标是为了拼接到我的Emp对象当中-->and age=#{age}</if><if test="gender!=null and gender !=''"><!-- 目标是为了拼接到我的Emp对象当中-->and gender=#{gender}</if></select>
表示如果字符串不是空对象或者不为空,那么才进行对sql的拼接,值得注意的是这边要手动添加and这一信息。
问题一:如果第一个emp_name是空,那么sql语句就变为
select * from t_emp where and 。。。。这显然有问题;
问题二:如果全是空那么,sql语句select * from t_emp where也有问题
这时可以添加1=1,然后if第一个标签中添加and即可,即:
<!-- List<Emp> getEmpByCondition(Emp emp);根据条件查询员工信息--><select id="getEmpByConditionOne" resultType="Emp">select * from t_emp where 1=1<if test="empName!=null and empName != ''">and emp_name = #{empName}</if><if test="age!=null and age !=''"> <!-- 目标是为了拼接到我的Emp对象当中-->and age=#{age}</if><if test="gender!=null and gender !=''"><!-- 目标是为了拼接到我的Emp对象当中-->and gender=#{gender}</if></select>
标签二:where标签,where标签有三个功能
作用一:自动生成where关键字
作用二:自动将多余的前面的and去掉,内容后多余的and没有办法去掉
作用三:where标签中没有任何一个标签成立,where中没有任何功能
可以发现,运用where标签也可以解决上面的问题。
<select id="getEmpByConditionTwo" resultType="Emp">select *from t_emp<where><if test="empName!=null and empName != ''">emp_name = #{empName}</if><if test="age!=null and age !=''"><!-- 目标是为了拼接到我的Emp对象当中-->and age=#{age}</if><if test="gender!=null and gender !=''"><!-- 目标是为了拼接到我的Emp对象当中-->and gender=#{gender}</if></where> </select>
标签三:trim标签
prefix与suffix:在标签前面后者后面添加指定内容prefixOverWrides和suffixOverrides:在标签中内容前面或者后面去掉指定内容
比方说(这个代码表示前面接上where后面去掉and然后进行操作):
<select id="getEmpByCondition" resultType="Emp">select* from t_emp<trim prefix="where" suffixOverrides="and"><if test="empName!=null and empName != ''">emp_name = #{empName} and</if><if test="age!=null and age !=''"><!-- 目标是为了拼接到我的Emp对象当中-->age=#{age} and</if><if test="gender!=null and gender !=''"><!-- 目标是为了拼接到我的Emp对象当中-->gender=#{gender}</if></trim> </select>
标签四:choose...when...otherwise(if...else if...else)进行处理操作,
其实也就是switch。。。case结构
<!-- List<Emp>getEmpByChoose(Emp emp);--><select id="getEmpByChoose" resultType="Emp">select *from t_emp<where><choose><when test="empName!=null and empName != ''">emp_name = #{empName}</when><when test="age!=null and age !=''">age=#{age}</when><when test="gender!=null and gender !=''">gender=#{gender}</when></choose></where></select>
标签四:forEach标签
Collection:设置要循环的数组或者集合 item:用一个数组表示数组或集合中的每一个数据 separator:用于设置每一次循环数据的分隔符 open:循环的所有内容,以什么开始 close:循环的所有内容,以什么结束
如下面所示:
<!-- void insertMoreEmp(@params(list)List<Emp> emps);--><insert id="insertMoreEmp">insert into t_emp values <!-- item 表示数组或者集合中的元素数据--><foreach collection="list" item="emp" separator=",">(null,#{emp.empName},#{emp.age},#{emp.gender},null)</foreach></insert><!-- void deleteMoreEmp(@Param("empIds") Integer[] empIds);--><delete id="deleteMoreEmp">delete from t_emp where emp_id in <!-- open和close用来设置左括号和右括号以什么开始--><foreach collection="empIds" item="empId" separator="," open="(" close=")">#{empId}</foreach></delete>
标签五:sql标签
所谓sql标签就是可以记录一段公共sql片段,在使用的地方通过include标签进行引入
比如说,如下所示:
<sql id="empColumns">emp_id,emp_name,age,gender,dept_id </sql>
<include></include>标签,在需要引用的地方,进行引用
<select id="getEmpByCondition" resultType="Emp">select <include refid="empColumns"></include> from t_emp<trim prefix="where" suffixOverrides="and"><if test="empName!=null and empName != ''">emp_name = #{empName} and</if><if test="age!=null and age !=''"><!-- 目标是为了拼接到我的Emp对象当中-->age=#{age} and</if><if test="gender!=null and gender !=''"><!-- 目标是为了拼接到我的Emp对象当中-->gender=#{gender}</if></trim> </select>
明哥复习Mybatis(2)相关推荐
- 明哥复习MyBatis(1)
这不是原创,借鉴尚硅谷的,不是原创 一.核心配置文件详解 ① <properties resource="jdbc.properties"/> 这个标签用于引入prop ...
- 【明哥报错簿】之 mybatis异常invalid comparison: java.util.Date and java.lang.String
[明哥报错簿]之 mybatis异常invalid comparison: java.util.Date and java.lang.String 参考文章: (1)[明哥报错簿]之 mybatis异 ...
- 继明哥的否定之后,java泰又出新作!明哥接码!
上次做那个系统是swing+jdbc实现的,无奈被明哥一句否定,数据库连接完全体现不了数据结构的作用,哎,这就是向小弟施加压力呀.人无压力不出油,经过10天的努力,终于李刚的通讯录更新为1.1版本! ...
- 华为云官网负责人明哥:我们是如何做到门面不倒,8个月挑战业界翘楚?
本文分享自华为云社区<华为云官网负责人明哥:我们是如何做到门面不倒,8个月挑战业界翘楚?>,原文作者:华为云社区精选 . 4月的一个周五傍晚,刚刚结束一场语音会议的明哥,拿起桌上的咖啡,一 ...
- 【学习笔记】明哥聊求职第二季
个人认为笔记记录的建议并不一定是对的.但针对这些问题,需要有自己的准备和思考,当然要诚实,坦然面对自己优劣 000:面试过程中,一定要明白所有问题都不是闲聊.要缜密思考,谨慎回答 001:你为什么离开 ...
- python 复制dict_Python高级数据类型之字典、集合【明哥陪你学Python-六】
上一篇我们简单对Python的基础数据类型做了说明和讲[Python高级数据类型之列表.元组],本篇我们继续针对Python的数据类型进行高级数据类型的介绍. 我们来先看一张图表: 字典(dict) ...
- 三年时间做到年薪百万,推荐明哥的职场心得
前段时间有朋友在圈子问怎么做职场,刚好认识的朋友中有人在做职场,因此推荐给大家. 明哥 在职场已经有十年有余,做过上百个项目,自己业余时间除了创作小说,写一些技术文章,同时也在分享自己的成长经历,职场 ...
- 明哥-带你三步开发JavaSE跨平台视频播放器
前言 这两天有一个学生来问我,说明哥JavaSE能不能开发一个简单版的视频播放器,网上的代码都太多了,这不,我这就写了一个简易版本的,利用 VLC media player 配合GUI 写了一个简单的 ...
- 【明哥版】2020最新Android Studio Win10 安装教程
前言 本篇文章主要明哥主要讲解Android开发环境的搭建,也就是Android Studio安装教程,为什么要写这篇文章呢?主要还是用于辅助明哥教学,方便学员查询资料,按照本片文章课下搭建开发环境. ...
最新文章
- php 的webservice类库NuSoap介绍
- java弱引用弱点_终于有人把Java强、软、弱、虚四种引用知识点整理出来了
- MyObjectUtil对象工具类
- 浙江省经信委与新华三签署战略合作协议
- js java post提交_如何从Express.js发送Post请求到另一个服务器(Java)?
- Anacoda 的 Python 包管理器 Conda 的常用使用命令
- BZOJ3591 最长上升子序列(状压dp)
- Android Gradle 完整指南(转)
- Java设计模式之工厂模式
- eoLinker-API_Shop_知识类API调用的代码示例合集:驾考题库、ISBN书号查询等
- windows11的ps界面字体显示过小
- linux下dbf是什么文件,DBF文件怎么打开?DBF文件的打开方法教程
- 计算机系统引导失败怎么办,win7系统引导选择失败怎么办|win7系统引导选择失败的解决方法...
- picker多选 vant_Vant picker 多级联动操作
- 微信小程序实现锚点效果 scroll-view的scroll-into-view属性
- 水星路由器wan口ip显示0_路由器WAN口获取不到IP地址怎么办?
- 【190319】VC++ C/S结构视频聊天软件源码源代码
- lqc_shell批量操作linux主机
- 微信公众号运营商,如何选择适合自己的微信第三方平台?
- 武汉理工大学计算机学院分流,2018考生来信——我在读的武汉理工大学