城市直播房产教育博客汽车
投稿投诉
汽车报价
买车新车
博客专栏
专题精品
教育留学
高考读书
房产家居
彩票视频
直播黑猫
投资微博
城市上海
政务旅游

MyBatis系列教程四一文读懂MyBatis动态SQL使用

4月28日 壹世缘投稿
  如果使用传统的JDBC编程,很多时候需要根据具体情况拼接SQL语句,这是一件很痛苦的事情。Mybatis为开发者提供了动态SQL语句的组装能力,并且如此强大的功能只有几个元素就可以完成,十分简单明了。大量的判断都可以在Mybatis的映射XML中完成。大大减少了编码的工作量,这也体现了Mybatis的灵活性和可维护性。下面首先了解一下Mybatis中常用的动态SQL元素。
  元素
  作用
  备注
  if
  判断语句
  单条件分支判断
  choose(when、otherwise)
  相当于Java中的casewhen
  多条件分支判断
  trim(where、set)
  辅助元素
  用于处理SQL拼装
  foreach
  循环语句
  在in语句等列举条件中常用
  下面,就将上述元素进行深入讨论。4。1if元素
  if元素是日常开发中较为常用的判断语句,相当于Java中的if语句,它常常与test属性联合使用。if元素使用方法比较简单,以第3章中的数据库为例,根据学生姓名进行模糊查询。映射器中代码如下:selectidfindStudentByStudentNameresultTypecn。bytecollege。entity。StudentparameterTypeStringSELECTSTUDENTID,STUDENTNAME,STUDENTAGE,STUDENTGENDERFROMSTUDENTWHERE11ifteststudentName!nullandstudentName!ANDSTUDENTNAMELIKECONCAT(,{studentName},)ifselect
  接口中定义方法:publicinterfaceStudentMapper{ListStudentfindStudentByStudentName(StringstudentName);}
  在示例代码中使用了if元素,if元素的test属性中判断studentName是否有值,如果有值则在已有SQL语句后拼接if元素中的语句,如果没有值则不拼接,下面首先传递studentName值做测试,代码如下:publicclassTest{publicstaticvoidmain(String〔〕args)throwsIOException{finalLoggerloggerLogger。getLogger(Test。class);InputStreamisResources。getResourceAsStream(mybatisconfig。xml);SqlSessionFactorysqlSessionFactorynewSqlSessionFactoryBuilder()。build(is);SqlSessionsessionsqlSessionFactory。openSession();StudentMappermappersession。getMapper(StudentMapper。class);1。ListStudentlistmapper。findStudentByStudentName(j);list。forEach(elogger。info(e));}}
  运行结果如下:
  可以看出,当studentName有值时拼接了SQL语句。在上例代码中注释1处的方法调用中传入null,再次测试,运行结果如下:
  从结果中可以看出SQL语句并没有拼接if元素中的语句。4。2choose、when、otherwise元素
  在上一小节中的if元素相当于Java当中的if分支结构,是一种非此即彼的关系,但是在很多时候开发者所面对的不一定是非此即彼的情形,可能有更多的选择或者分支,此时虽说if可以满足需要,但是代码显得很蹩脚。因此Mybatis为开发者提供了类似于多分支的结构,并且这种结构在做根据条件搜索时显得尤为方便,避免了繁复的代码和判断。例如:根据学生姓名或者年龄或者性别检索数据。在映射器中配置select元素:selectidsearchStudentresultTypecn。bytecollege。entity。StudentparameterTypecn。bytecollege。entity。StudentSELECTSTUDENTID,STUDENTNAME,STUDENTAGE,STUDENTGENDERFROMSTUDENTWHERE11choosewhenteststudentName!nullandstudentName!ANDSTUDENTNAME{studentName}whenwhenteststudentAge!nullandstudentAge!ANDSTUDENTAGE{studentAge}whenwhenteststudentGender!nullandstudentGender!ANDSTUDENTGENDER{studentGender}whenotherwiseANDSTUDENTIDISNOTNULL;otherwisechooseselect
  Mybatis会根据参数的设置进行判断来动态组装SQL,以满足不同的业务需求。接口中定义方法:publicinterfaceStudentMapper{ListStudentsearchStudent(Studentstudent);}
  新建测试类代码如下:publicclassTest{publicstaticvoidmain(String〔〕args)throwsIOException{finalLoggerloggerLogger。getLogger(Test。class);InputStreamisResources。getResourceAsStream(mybatisconfig。xml);SqlSessionFactorysqlSessionFactorynewSqlSessionFactoryBuilder()。build(is);SqlSessionsessionsqlSessionFactory。openSession();StudentMappermappersession。getMapper(StudentMapper。class);StudentstudentnewStudent();student。setStudentName(Jack);ListStudentlistmapper。searchStudent(student);list。forEach(elogger。info(e));}}
  运行结果如下图:
  4。3where、trim、set元素4。3。1where元素
  在上面的代码中,每条SQL语句中都添加了一个11这个条件,这是因为如果不添加这个条件上一小节中的SQL语句可能会下面这样错误的SQL语句:SELECTSTUDENTID,STUDENTNAME,STUDENTAGE,STUDENTGENDERFROMSTUDENTWHEREANDSTUDENTNAME?
  但是加上这个莫名其妙的条件又显得很奇怪,在这里就可以使用where元素以达到逾期的效果。对上一小节中的SQL语句进行修改,去掉11,并且将choose。。。when修改为where和if,代码如下:selectidsearchStudentresultTypecn。bytecollege。entity。StudentparameterTypecn。bytecollege。entity。StudentSELECTSTUDENTID,STUDENTNAME,STUDENTAGE,STUDENTGENDERFROMSTUDENTwhereifteststudentName!nullandstudentName!ANDSTUDENTNAME{studentName}ififteststudentAge!nullandstudentAge!ANDSTUDENTAGE{studentAge}ififteststudentGender!nullandstudentGender!ANDSTUDENTGENDER{studentGender}ifwhereselect
  当where元素中的条件只要有一个成立时,会在已有SQL语句后拼接where以及成立的条件,如果没有条件成立,则不会拼接SQL语句,也不会拼接where,下面的示例将演示这种情况:publicclassTest{publicstaticvoidmain(String〔〕args)throwsIOException{finalLoggerloggerLogger。getLogger(Test。class);InputStreamisResources。getResourceAsStream(mybatisconfig。xml);SqlSessionFactorysqlSessionFactorynewSqlSessionFactoryBuilder()。build(is);SqlSessionsessionsqlSessionFactory。openSession();StudentMappermappersession。getMapper(StudentMapper。class);ListStudentlistmapper。searchStudent(null);list。forEach(elogger。info(e));}}
  运行结果如下:
  在测试类中方法内传入了null,所有的参数都为null,不满足where元素中if元素的条件,因此Mybatis并没有拼接where及条件。4。3。2trim元素
  有时候需要去掉一些特殊的SQL语法,比如常见的and、or。使用trim元素就可以达到这种效果。selectidtrimTestparameterTypeStringSELECTSTUDENTID,STUDENTNAME,STUDENTAGE,STUDENTGENDERFROMSTUDENTtrimprefixwhereprefixOverridesandifteststudentName!nullANDSTUDENTNAME{studentName}iftrimselect
  注意上面的SQL语句,如果studentName不等于null时,此时的SQL语句会变成:SELECTSTUDENTID,STUDENTNAME,STUDENTAGE,STUDENTGENDERFROMSTUDENTANDSTUDENTNAME{studentName}
  这条SQL语句会产生语法错误,trim元素此时就要发挥作用了,会将and替换为where,也就是说trim元素的作用就是将prefixOverrides中配置的值替换为prefix中的值。4。3。3set元素
  在日常开发中更新操作出现的也比较频繁,但是在更新操作中通常会只更新几个字段,而不是全部更新,如果将所有的字段都发送给数据库,这样就会带来不必要的内存和宽带开销,set元素就可以解决这种问题,例如更新学生信息。updateidupdateStudentparameterTypecn。bytecollege。entity。StudentUPDATESTUDENTsetifteststudentName!nullandstudentName!STUDENTNAME{studentName},ififteststudentAge!nullandstudentAge!STUDENTAGE{studentAge},ififteststudentGender!nullandstudentGender!STUDENTGENDER{studentGender}ifsetWHERESTUDENTID{studentId}update
  接口中定义方法:publicinterfaceStudentMapper{intupdateStudent(Studentstudent);}
  新建测试类:publicclassTest{publicstaticvoidmain(String〔〕args)throwsIOException{finalLoggerloggerLogger。getLogger(Test。class);InputStreamisResources。getResourceAsStream(mybatisconfig。xml);SqlSessionFactorysqlSessionFactorynewSqlSessionFactoryBuilder()。build(is);SqlSessionsessionsqlSessionFactory。openSession();StudentMappermappersession。getMapper(StudentMapper。class);StudentstudentnewStudent();student。setStudentId(7);student。setStudentAge(20);mapper。updateStudent(student);session。commit();}}
  运行结果如下:
  因为传入的参数中只有studentAge,因此Mybatis在拼接SQL语句时只拼接了满足studentAge的条件。4。4foreach元素
  foreach元素是一个循环语句,作用是遍历集合,它能够很好的支持数组和List、Set接口的集合,对此提供遍历功能。例如删除多条数据,就可以使用foreach元素。deleteidbatchDeleteStudentparameterTypeListDELETEFROMSTUDENTWHERESTUDENTIDINforeachcollectionlistopen(close)separator,itemid{id}foreachdeletecollection:配置的是传递进来的参数名称,可以是一个数组或者List、set等集合item:配置的是循环中的元素,可以理解为数组或者集合中的元素的名称open和close:配置的是以什么符号将这些集合元素包装起来separator:是各个元素的分隔符
  接口中定义方法:publicinterfaceStudentMapper{intbatchDeleteStudent(Listlist);}
  新建测试类:publicclassTest{publicstaticvoidmain(String〔〕args)throwsIOException{finalLoggerloggerLogger。getLogger(Test。class);InputStreamisResources。getResourceAsStream(mybatisconfig。xml);SqlSessionFactorysqlSessionFactorynewSqlSessionFactoryBuilder()。build(is);SqlSessionsessionsqlSessionFactory。openSession();StudentMappermappersession。getMapper(StudentMapper。class);ListIntegerlistnewArrayList();list。add(1);list。add(2);mapper。batchDeleteStudent(list);session。commit();}}
  运行结果如下:
  4。5Mybaits分页4。5。1RowBounds分页
  Mybatis具有分页功能,其为开发者提供了一个类RowBounds,开发者可以使用RowBounds分页,但是RowBounds分页有一个很重要的缺陷,就是会将所有的数据查询出来后根据从第几条到第几条取出数据返回,当数据量比较小时,这么做没有任何问题,但是当数据量大时,这么做无疑对数据库造成了很大的负担。RowBounds主要定义了两个参数,offset和limit,offset代表从第几行开始读取数据,limit则是限制返回的记录数。在默认情况下offset设置为0,而limit这是Java所允许的最大整数(2147483647)。下面通过示例学习RowBounds的用法:selectidfindStudentByPageresultTypecn。bytecollege。entity。StudentSELECTSTUDENTID,STUDENTNAME,STUDENTAGE,STUDENTGENDERFROMSTUDENTselect
  在接口中定义方法:publicinterfaceStudentMapper{ListStudentfindStudentByPage(RowBoundsrowBounds);}
  新建测试类:publicclassTest{publicstaticvoidmain(String〔〕args)throwsIOException{finalLoggerloggerLogger。getLogger(Test。class);InputStreamisResources。getResourceAsStream(mybatisconfig。xml);SqlSessionFactorysqlSessionFactorynewSqlSessionFactoryBuilder()。build(is);SqlSessionsessionsqlSessionFactory。openSession();StudentMappermappersession。getMapper(StudentMapper。class);1。ListStudentlistmapper。findStudentByPage(newRowBounds(0,5));list。forEach(elogger。info(e));}}
  在代码中注释1处,调用方法是传入RowBounds对象。即可完成分页。运行结果如下:
  从结果中可以看出使用RowBounds分页时,会将所有的数据都查询出来,然后从数据中截取目标数据,也就是通常所说的逻辑分页。4。5。2插件分页
  基于RowBounds分页存在一定缺陷,通常会推荐使用自定义插件分页,并且又第三方提供了性能不错的分页插件PageHelper,下面就改插件做简单示范:首先,在pom。xml中添加依赖dependencygroupIdcom。github。pagehelpergroupIdpagehelperartifactIdversion最新版本versiondependency
  在Mybatis全局文件中进行配置:pluginsplugininterceptorcom。github。pagehelper。PageInterceptorpluginplugins
  由于Mybatis的插件是基于代理拦截实现,所以继续使用上例中的接口及测试类,插件会自动帮助开发者在SQL中拼接limit关键字。运行结果如下:
  关于该插件的详细用法,可前往PageHelper插件官网进行查阅。
投诉 评论 转载

布克詹娜出游,谣言不攻自破,独行侠想用阴招,无奈库里爱比金坚NBA季后赛如火如荼进行,已经被淘汰的太阳,灰熊等队球员也进入了假期,太阳当家布克在21日参加了卡戴珊家族Travis和Kourtney的婚礼,期间布克还亲吻了詹娜的头部,而詹……V观财报招商证券被立案!刚被警示,高管频繁变动中新经纬8月12日电招商证券被证监会立案了,牵涉到2014年的独立财务顾问业务工作。涉2014年独立财务顾问业务工作12日晚间,招商证券公告称,当天收到中国证监会《……32岁丁宁喜迎新岗位!打扮精致惊艳亮相,刘国梁果然没看错人近日,丁宁大满贯六周年‘的微博话题的阅读量已超三十余万,回顾丁宁在乒乓球历史上留下的一个个惊心动魄,激励人心的故事。2016年的里约奥运会完成了迟来四年的大满贯,也是中国乒乓球……相守10年生下4个孩子,和奥尼尔离婚时,香妮得到了多少赔偿?看到如今的奥尼尔感情处处碰壁,着实让人觉得心疼,拥有数亿美元的资产,拥有巨大的名气,追求超大号超模被拒绝,追求东契奇的妈妈被拒绝,好好的一个NBA活宝混的和在家给网红点赞的杜兰……输了!0分0助0断0帽!哈登真被防死了?费城VS热火,92106。恩比德遭遇严重伤势,暂时无法登场,于是这组对决二轮显而易见,成了矛盾之间的战争。登哥这根联盟最强之一的攻击之矛,能否击破热火多名肉盾组成的极限防守?目……粉丝太热情被揍?出手的是拳王转载自:新闻坊前世界重量级拳王迈克泰森摊上麻烦了。当地时间4月21日报道,拳王泰森近日在乘坐飞机时被过度热情的醉酒男粉丝骚扰,忍无可忍的他起……华为智能门锁系列即将发售续航10个月最低2499元起2022年4月28日19:00,华为折叠旗舰及全场景新品发布会以线上直播形式召开。发布会中,华为终端业务CEO余承东宣布了华为智能门锁系列的发售时间与价格。华为智能门锁售价24……4万年前8岁男孩容貌再现鼻背凹陷、棕色眼睛、鼻头略微翘起日前,吉林大学生物考古团队向记者展示了运用数字化三维人像复原技术,依据旧石器时代遗址特希克塔什洞穴出土的尼安德特人男孩头骨化石,复原出的小男孩形……全国房地产开发投资罕见降幅10!释放什么信号,今年房价怎么走1月17日,国家统计局发布2022年全年房地产开发投资与销售数据。尽管行业政策面释放宽松信号,但2022年多项房地产数据指标仍保持下探,其中全国房地产开发投资额同比降幅为……我的2022读书总结导语实在没有想到,2022年的新冠疫情,会以一种更为疯狂的方式、摧枯拉朽般的影响着每个人的生活。原本以为,怎么样了一两年也该结束了吧?事实上,不管是新冠疫情,还是未来别的……苏联领事馆沙面行(5)沙面大街68号,1916年建,曾作苏联领事馆、苏联驻华商务代表团广州办事处,是沙面岛上重要的近现代外国领事馆建筑。苏联领事馆旧址为砖、钢筋混凝土结构三层楼房,英国维多利亚式建筑……MyBatis系列教程四一文读懂MyBatis动态SQL使用如果使用传统的JDBC编程,很多时候需要根据具体情况拼接SQL语句,这是一件很痛苦的事情。Mybatis为开发者提供了动态SQL语句的组装能力,并且如此强大的功能只有几个元素就……
复旦大学钠电失效机制与富钠阴极长循环全电池宇宙到底有多大?宇宙之外有什么?相比宇宙之外,宇宙只像个原子大涨450元吨,复合肥拐点要来了?马斯克再夸中国在可再生能源发电和电动汽车领域处于世界领先地位秋季,心静如画,心净无尘如何预防泌尿系结石?骁龙8Gen2机型首批机型盘点,一定要做一个合格的等等党拉尼娜现象卷土重来!已连续出现3年,我国今冬注定更冷?韩国第一夫人吃路边摊也有大排场!穿大衣抱娃姿势翻车,真接地气关于人性的大实话新青岩中国年青岩寻坊正式开街浙江6条适合初秋徒步的古道,有你走过的吗?
小学生作文我发现了生活中的美生命名人名言警句武汉贩卖毒品罪量刑标准是怎么规定的水帘洞是谁替孙悟空安排好的?水帘洞真正的主人是谁?微信聊天记录查联系方式(微信聊天记录在哪里查)极乐迪斯科首席设计师与编剧起诉开发商ZAUM瘦腿霜是运动前涂还是运动后涂瘦腿霜的成分腾冲旅游攻略(腾冲自由行线路攻略)新田靶向引才带活县域经济儿童奶瓶齿影响吃饭吗长款过膝呢子大衣时尚优雅穿出女王气场加快推进大学治理体系现代化

友情链接:中准网聚热点快百科快传网快生活快软网快好知文好找江西南阳嘉兴昆明铜陵滨州广东西昌常德梅州兰州阳江运城金华广西萍乡大理重庆诸暨泉州安庆南充武汉辽宁