【MyBatis】篇三.自定义映射resultMap和动态SQL
创始人
2024-06-02 00:14:24
0

= = = =MyBatis整理= = = =

篇一.MyBatis环境搭建与增删改查
篇二.MyBatis查询与特殊SQL
篇三.自定义映射resultMap和动态SQL
篇四.MyBatis缓存和逆向工程

文章目录

  • 1、自定义映射
    • P1:测试数据准备
    • P2:字段和属性的映射关系
    • P3:多对一的映射关系
    • P4:一对多的映射关系
  • 2、动态SQL
    • 2.1 IF标签
    • 2.2 where标签
    • 2.3 trim标签
    • 2.4 choose、when、otherwise标签
    • 2.5 foreach标签
    • 2.6 SQL标签

1、自定义映射

若字段名和实体类的属性名不一致,则需要自定义映射。

P1:测试数据准备

员工表:
在这里插入图片描述
部门表:
在这里插入图片描述

定义对应的实体类:(注意,字段名是下划线命名,属性名是驼峰命名,不再一致了)
在这里插入图片描述

定义Mapper接口和映射文件:

在这里插入图片描述

P2:字段和属性的映射关系

当字段名和实体类中的属性名不一致,但是字段名符合数据库的规则(使用_),实体类中的属性名符合Java的规则(使用驼峰),此时使用之前的自动映射resultType,则命名不一致的属性值为null,解决思路有三种:

思路一:给字段名起别名,使其和属性名保持一致


思路二:设置全局配置,将下划线_自动映射为驼峰

在核心配置文件mybatis-config.xml中:



此时,SQL语句正常写即可。

思路三:使用resultMap,不再使用之前的resultType做自动映射





resultMap即设置自定义映射关系:

  • 属性:
    。 id:我定义的映射的唯一标识,不能重复,给select标签中的resultMap属性用
    。 type:查询的数据要映射的实体类的类型
  • 子标签:
    。 id:设置主键的映射关系
    。 result:设置普通字段的映射关系
  • 子标签属性:
    。 property:设置映射关系中实体类中的属性名
    。 column:设置映射关系中表中的字段名

运行结果:
在这里插入图片描述

P3:多对一的映射关系

多对一的时候,在’多’的这边设置,设置’一’所对应的对象;在’一’那边,设置’多’的对象集合 。处理多对一的映射关系(如查询企业员工信息及其部门)有三种实现方式:

public class Emp {  private Integer eid;  private String empName;  private Integer age;  private String sex;  private String email;  /*** 这里设置'一'所对应的对象*/private Dept dept;//...构造器、get、set方法等
}

思路一:使用级联属性赋值




思路二:通过association处理多对一的映射

  • association:处理多对一映射关系
  • property:需要处理多对一映射关系的属性名
  • javaType:该属性的类型



以上的逻辑是:在association中写要处理多对一关系的属性名dept,再说明该属性的Java类---->知道类型,通过反射拿到该类型的属性did和deptName---->将查询出来的字段赋值给属性---->Dept类的对象有了---->赋值给属性dept

思路三:分步查询处理多对一的映射

先查询员工信息–>拿到部门id–>根据部门id查询部门信息—>将信息赋值给dept属性

引用属性--那个属性的值也是一个对象,丈夫是一个对象:
有姓名属性、年龄属性、妻子属性。妻子属性就是一个引用属性,里面是个对象,有它自己的属性
//EmpMapper里的方法
/*** 通过分步查询,员工及所对应的部门信息* 分步查询第一步:查询员工信息*/
Emp getEmpAndDeptByStepOne(@Param("eid") Integer eid);
  • property:即要处理多对一映射关系的属性名
  • select:即设置分布查询的sql的唯一标识(namespace.SQLId或mapper接口的全类名.方法名)
  • column:设置分布查询的条件,要根据员工表的did去查询部门信息,即第二个SQL要根据什么去查



第二步:

//DeptMapper里的方法
/*** 通过分步查询,员工及所对应的部门信息* 分步查询第二步:通过did查询员工对应的部门信息* 这里的查询结果要给Emp的dept属性赋值,所以返回类型Dept*/
Dept getEmpAndDeptByStepTwo(@Param("did") Integer did);




测试类:

@Test
public void testGetEmpAndDeptByStep() {SqlSession sqlSession = SqlSessionUtils.getSqlSession();EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);Emp emp = emmpMapper.getEmpAndDeptByStepOne(5);System.out.println(emp);
}

运行结果:
在这里插入图片描述
梳理下逻辑:
在这里插入图片描述

分步查询的好处–延迟加载

分步查询,实现一个功能分了两步,但这两步各自也是一个单独的功能。这就分步查询的好处—实现延迟加载

在核心配置文件中配置全局信息(setting标签):

  • lazyLoadingEnabled:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载
  • aggressiveLazyLoading:当开启时,任何方法的调用都会加载该对象的所有属性。 否则,每个属性会按需加载

此时:我只获取员工名称,可以发现第二句SQL并未执行,这就是按需加载,获取的数据是什么,就只会执行相应的sql

在这里插入图片描述

而当获取部门信息的时候,两句就都会执行。为了清晰看到效果,先关掉延迟加载,可以看到是两句SQL都执行完了,再拿数据:
在这里插入图片描述

再开启延迟加载,可以看到是先执行了一句SQL,拿到了员工姓名,后面需要部门信息的时候,又执行了第二句SQL,这就是按需加载!!!
在这里插入图片描述
更改了全局设置,是否延迟加载则是对所有SQL的。当开启了全局的延迟加载(注意fetchType的前提是开启全局),要想单独控制某一个,可通过association和collection中的fetchType属性设置当前的分步查询是否使用延迟加载:

  • fetchType=“lazy(延迟加载)”
  • fetchType=“eager(立即加载)”

P4:一对多的映射关系

多对一的时候,在’多’的这边设置,设置’一’所对应的对象;在’一’那边,设置’多’的对象集合

public class Dept {private Integer did;private String deptName;//'多'的类型的集合private List emps;//...构造器、get、set方法等
}

思路一:使用collection

  • collection:处理一对多的映射关系
  • ofType:表示该属性所对应的集合中存储的数据的类型
public interface DeptMapper{/*** 查询部门即其下的所有员工信息*/Dept getDeptAndEmp(@Param("did") Integer did);
}



思路二:分步查询

第一步:

public interface DeptMapper{/*** 通过分步查询,查询部门及对应的所有员工信息* 分步查询第一步:查询部门信息*/Dept getDeptAndEmpByStepOne(@Param("did") Integer did);
}



第二步:

public interface EmpMapper{/*** 通过分步查询,查询部门及对应的所有员工信息* 分步查询第二步:根据部门id查询部门中的所有员工*/List getDeptAndEmpByStepTwo(@Param("did") Integer did);
}

结果:
在这里插入图片描述
当然,分布查询在这儿也可以得到验证:
在这里插入图片描述


2、动态SQL

Mybatis框架的动态SQL技术是一种根据特定条件动态拼装SQL语句的功能,它存在的意义是为了解决拼接SQL语句字符串时的痛点问题

2.1 IF标签

public interface DynamicSQLMapper{/*** 多条件查询*/List getEmpByCondition(Emp emp);
}
  • if标签可通过test属性对表达式进行判断,若表达式的结果为true,则标签中的内容会拼接到SQL中,反之标签中的内容不会拼接。
  • 在where后面添加一个恒成立条件1=1,这个条件不会影响查询结果,而又可以很好的拼接后面的SQL:当empName传过来为空,select * from t_emp where and age = ? and sex = ? and email = ?,此时where与and连用,SQL语法错误

测试:
在这里插入图片描述

2.2 where标签

当where标签中有内容时,会自动生成where关键字,并将内容前多余的and或者or去掉,而当where标签中没内容时,where关键字也就不再生成。


where标签和if标签一般配合使用:

  • 若where标签中的if条件都不满足,则where标签没有任何功能,即不会添加where关键字
  • 若where标签中的if条件满足,则where标签会自动添加where关键字,并将条件最前方多余的and/or去掉


emp_name = #{empName} and

age = #{age}

当empName有值,age为空,则SQL为:

select * from d_emp where emp_name="llg" and
//此处where标签去不掉and了

2.3 trim标签

trim用于去掉或添加标签中的内容,当标签中有内容的时候:

  • prefix:在trim标签中的内容的前面添加某些指定内容
  • suffix:在trim标签中的内容的后面添加某些指定内容
  • prefixOverrides:在trim标签中的内容的前面去掉某些指定内容
  • suffixOverrides:在trim标签中的内容的后面去掉某些指定内容

当标签中没有内容的时候,trim标签也没有任何效果


测试类:

//测试类
@Test
public void getEmpByCondition() {SqlSession sqlSession = SqlSessionUtils.getSqlSession();DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);List emps= mapper.getEmpByCondition(new Emp(null, "甲", null, null, null, null));System.out.println(emps);
}

在这里插入图片描述

2.4 choose、when、otherwise标签

choose…when…otherwise相当于if…else if…else

  • when即if或者else if,至少要有一个,when后面的test条件成立,则拼接
  • otherwise相当于else,最多只能有一个


测试程序:

@Test
public void getEmpByChoose() {SqlSession sqlSession = SqlSessionUtils.getSqlSession();DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);List emps = mapper.getEmpByChoose(new Emp(null, "", null, "", "", null));System.out.println(emps);
}

结果:
在这里插入图片描述

2.5 foreach标签

foreeach标签的属性有:

  • collection:设置要循环的数组或集合
  • item:表示集合或数组中的每一个数据
  • separator:设置循环体之间的分隔符,分隔符前后默认有一个空格,如,
  • open:设置foreach标签中的内容的开始符
  • close:设置foreach标签中的内容的结束符

通过数组实现批量删除

public interface DynamicSQLMapper{/*** 通过数组实现批量删除*/int deleteMoreByArray(List eids);
}

只论SQL,批量删除的实现可以通过以下两种写法:

delete from t_emp where eid in (6,7,8);
delte from t_emp where eid=6 or eid=7 or eid=8;

关于第一种SQL的实现:

在这里插入图片描述
优化一下:


delete from t_emp where eid = #{eid}

关于第二种SQL的实现:


delete from t_emp where eid in#{eid}

测试:

@Test
public void deleteMoreByArray() {SqlSession sqlSession = SqlSessionUtils.getSqlSession();DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);int result = mapper.deleteMoreByArray(new Integer[]{6, 7, 8});System.out.println(result);
}

结果:
在这里插入图片描述

在这里插入图片描述

通过集合实现批量插入

public interface DynamicSQLMapper{/*** 通过集合实现批量添加*/int insertMoreByList(List emps);
}

只说SQL,写法应该是:

insert into t_emp values(a1,a2,a3),(b1,b2,b3),(v1,v2,v3);

使用foreach动态实现:


insert into t_emp values(null,#{emp.empName},#{emp.age},#{emp.sex},#{emp.email},null)

注意,这里不用open和close,批量插入的原SQL是每条数据中有括号,即每次循环有括号,而不是删除SQL中的开头和结尾有括号。

//测试程序
@Test
public void insertMoreByList() {SqlSession sqlSession = SqlSessionUtils.getSqlSession();DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);Emp emp1 = new Emp(null,"a",1,"男","123@321.com",null);Emp emp2 = new Emp(null,"b",1,"男","123@321.com",null);List emps = Arrays.asList(emp1, emp2);int result = mapper.insertMoreByList(emps);System.out.println(result);
}

结果:
在这里插入图片描述

2.6 SQL标签

在映射文件中,声明一段SQL片段,把常用的一段SQL进行记录,在要使用的地方使用include标签进行引入。

  • 声明
eid,emp_name,age,sex,email
  • 引用

上一篇:std::copy与memcpy比较

下一篇:Vue(20-30)

相关内容

热门资讯

小学唐诗 小学唐诗  引导语:下面是小编为大家收集的小学唐诗60首,欢迎大家阅读。  1、江南 汉乐府  江南...
小学一到六年级古诗 人教版小学一到六年级古诗汇总  看到厚厚的一摞小学12册语文课本,小编的心中也是感慨万千,这些,与学...
寻找描写茶花的诗句 寻找描写茶花的诗句  茶花是中国传统的观赏花卉,“十大名花”中排名第八,亦是世界名贵花木之一,在诗人...
辛弃疾诗词集 辛弃疾诗词集  引言:辛弃疾南宋豪放派词人、将领,有“词中之龙”之称。与苏轼合称“苏辛”,与李清照并...
花和雨的诗句 花和雨的诗句  花自飘零水自流。一种相思,两处闲愁。以下是花和雨的诗句,欢迎阅读!  花和雨的诗句 ...
风花雪月的优美诗句 风花雪月的优美诗句  风的诗句:  1、《春晓》  唐·孟浩然  春眠不觉晓,处处闻啼鸟。  夜来风...
写哪些赞美老师的诗句 写哪些赞美老师的诗句  刻在木板上的名字未必不朽,刻在石头上的名字也未必流芳百世;老师,您的名字刻在...
离别惆怅的诗句是 离别惆怅的诗句是  惆怅就是因为心中郁闷而不知道该干什么,忧伤和悲哀是表示的一种心理状态,而惆怅是强...
冰心诗集《繁星》全文(2) 冰心诗集《繁星》全文  八十九  花儿低低的对看花的人说  "少顾念我罢  我的朋友!  让我自己安...
船字开头的诗句 船字开头的诗句  船,指的`是:利用水的浮力,依靠人力、风帆、发动机(如蒸气机、燃气涡轮、柴油引擎、...
赞美端午节的优美诗句 赞美端午节的优美诗句  端午节起源于春秋战国,距今已有两千多年。关于端午节的'诗句有哪些呢?  1、...
春天的诗句 春天的诗句(通用205句)  在日复一日的学习、工作或生活中,大家都经常接触到诗句吧,诗句节奏上鲜明...
《摊破浣溪沙·菡萏香销翠叶残... 《摊破浣溪沙·菡萏香销翠叶残》古诗赏析  古诗带拼音版  tān pò huàn xī shā ·h...
春雨的诗句 春雨的诗句  《春雨二首》  年代:唐 作者: 李建勋  春霖未免妨游赏,唯到诗家自有情。  花径不...
描写月亮的现代诗句 导语:月光如水,静静地洒在地上,给大地披上银灰色的纱裙。她穿着白色的衬衫,娴静而安详,温柔而大方,她...
郭沫若的诗集 郭沫若的诗集  郭沫若(1892年~1978年),男,汉族,中国现代著名学者、文学家、历史学家、古文...
描写玫瑰花的经典诗句 描写玫瑰花的经典诗句  日高闲步下堂阶,细草春莎没绣鞋。折得玫瑰花一朵,凭君簪向凤凰钗。  1、《司...
唐诗之张旭:桃花溪 唐诗三百首之张旭:桃花溪唐诗三百首全集《桃花溪》作者:张旭隐隐飞桥隔野烟,石矾西畔问渔船。桃花尽日随...
最富有哲理的诗句 最富有哲理的诗句  诗句,就是组成诗词的句子。诗句通常按照诗文的格式体例,限定每句字数的多少。中国最...
经典名人古诗 经典名人古诗汇总  在日复一日的学习、工作或生活中,大家一定都接触过一些使用较为普遍的古诗吧,古诗言...