范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

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

  如果使用传统的JDBC编程,很多时候需要根据具体情况拼接SQL语句,这是一件很痛苦的事情。Mybatis为开发者提供了动态SQL语句的组装能力,并且如此强大的功能只有几个元素就可以完成,十分简单明了。大量的判断都可以在Mybatis的映射XML中完成。大大减少了编码的工作量,这也体现了Mybatis的灵活性和可维护性。下面首先了解一下Mybatis中常用的动态SQL元素。
  元素
  作用
  备注
  if
  判断语句
  单条件分支判断
  choose(when、otherwise)
  相当于Java中的case when
  多条件分支判断
  trim(where、set)
  辅助元素
  用于处理SQL拼装
  foreach
  循环语句
  在in语句等列举条件中常用
  下面,就将上述元素进行深入讨论。 4.1 if元素
  if元素是日常开发中较为常用的判断语句,相当于Java中的if语句,它常常与test属性联合使用。   if元素使用方法比较简单,以第3章中的数据库为例,根据学生姓名进行模糊查询。  映射器中代码如下: 
  接口中定义方法:  public interface StudentMapper {      List findStudentByStudentName(String studentName);  }
  在示例代码中使用了if元素,if元素的test属性中判断studentName是否有值,如果有值则在已有SQL语句后拼接if元素中的语句,如果没有值则不拼接,下面首先传递studentName值做测试,代码如下:  public class Test {      public static void main(String[] args) throws IOException {          final Logger logger = Logger.getLogger(Test.class);          InputStream is = Resources.getResourceAsStream("mybatis-config.xml");            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);          SqlSession session = sqlSessionFactory.openSession();          StudentMapper mapper = session.getMapper(StudentMapper.class);          //1.          List list = mapper.findStudentByStudentName("j");          list.forEach(e->logger.info(e));      }  }
  运行结果如下:
  可以看出,当studentName有值时拼接了SQL语句。  在上例代码中注释1处的方法调用中传入null,再次测试,运行结果如下:
  从结果中可以看出SQL语句并没有拼接if元素中的语句。4.2 choose、when、otherwise元素
  在上一小节中的if元素相当于Java当中的if分支结构,是一种非此即彼的关系,但是在很多时候开发者所面对的不一定是非此即彼的情形,可能有更多的选择或者分支,此时虽说if可以满足需要,但是代码显得很蹩脚。因此Mybatis为开发者提供了类似于多分支的结构,并且这种结构在做根据条件搜索时显得尤为方便,避免了繁复的代码和判断。例如:根据学生姓名或者年龄或者性别检索数据。   在映射器中配置select元素: 
  Mybatis会根据参数的设置进行判断来动态组装SQL,以满足不同的业务需求。   接口中定义方法: public interface StudentMapper {      List searchStudent(Student student);  }
  新建测试类代码如下:  public class Test {      public static void main(String[] args) throws IOException {          final Logger logger = Logger.getLogger(Test.class);          InputStream is = Resources.getResourceAsStream("mybatis-config.xml");            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);          SqlSession session = sqlSessionFactory.openSession();          StudentMapper mapper = session.getMapper(StudentMapper.class);            Student student = new Student();          student.setStudentName("Jack");            List list = mapper.searchStudent(student);          list.forEach(e->logger.info(e));      }  }
  运行结果如下图:
  4.3 where、trim、set元素4.3.1 where元素
  在上面的代码中,每条SQL语句中都添加了一个1=1这个条件,这是因为如果不添加这个条件上一小节中的SQL语句可能会下面这样错误的SQL语句:  SELECT STUDENT_ID,STUDENT_NAME,STUDENT_AGE,STUDENT_GENDER FROM STUDENT WHERE  AND STUDENT_NAME = ?
  但是加上这个莫名其妙的条件又显得很奇怪,在这里就可以使用where元素以达到逾期的效果。对上一小节中的SQL语句进行修改,去掉1=1,并且将choose...when修改为where和if,代码如下:  
  当where元素中的条件只要有一个成立时,会在已有SQL语句后拼接where以及成立的条件,如果没有条件成立,则不会拼接SQL语句,也不会拼接where,下面的示例将演示这种情况: public class Test {     public static void main(String[] args) throws IOException {         final Logger logger = Logger.getLogger(Test.class);         InputStream is = Resources.getResourceAsStream("mybatis-config.xml");          SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);         SqlSession session = sqlSessionFactory.openSession();         StudentMapper mapper = session.getMapper(StudentMapper.class);          List list = mapper.searchStudent(null);         list.forEach(e->logger.info(e));     } }
  运行结果如下:
  在测试类中方法内传入了null,所有的参数都为null,不满足where元素中if元素的条件,因此Mybatis并没有拼接where及条件。4.3.2 trim元素
  有时候需要去掉一些特殊的SQL语法,比如常见的and、or。使用trim元素就可以达到这种效果。 
  注意上面的SQL语句,如果studentName不等于null时,此时的SQL语句会变成: SELECT STUDENT_ID,STUDENT_NAME,STUDENT_AGE,STUDENT_GENDER FROM STUDENT AND STUDENT_NAME = #{studentName}
  这条SQL语句会产生语法错误,trim元素此时就要发挥作用了,会将and替换为where,也就是说trim元素的作用就是将prefixOverrides中配置的值替换为prefix中的值。 4.3.3 set元素
  在日常开发中更新操作出现的也比较频繁,但是在更新操作中通常会只更新几个字段,而不是全部更新,如果将所有的字段都发送给数据库,这样就会带来不必要的内存和宽带开销,set元素就可以解决这种问题,例如更新学生信息。      UPDATE STUDENT                           STUDENT_NAME = #{studentName},                               STUDENT_AGE = #{studentAge},                               STUDENT_GENDER = #{studentGender}                   WHERE STUDENT_ID = #{studentId} 
  接口中定义方法: public interface StudentMapper {     int updateStudent(Student student); }
  新建测试类: public class Test {     public static void main(String[] args) throws IOException {         final Logger logger = Logger.getLogger(Test.class);         InputStream is = Resources.getResourceAsStream("mybatis-config.xml");          SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);         SqlSession session = sqlSessionFactory.openSession();         StudentMapper mapper = session.getMapper(StudentMapper.class);          Student student = new Student();         student.setStudentId(7);         student.setStudentAge(20);          mapper.updateStudent(student);         session.commit();     } }
  运行结果如下:
  因为传入的参数中只有studentAge,因此Mybatis在拼接SQL语句时只拼接了满足studentAge的条件。4.4 foreach元素
  foreach元素是一个循环语句,作用是遍历集合,它能够很好的支持数组和List、Set接口的集合,对此提供遍历功能。例如删除多条数据,就可以使用foreach元素。      DELETE FROM STUDENT WHERE STUDENT_ID IN              #{id}      collection:配置的是传递进来的参数名称,可以是一个数组或者List、set等集合 item:配置的是循环中的元素,可以理解为数组或者集合中的元素的名称 open和close:配置的是以什么符号将这些集合元素包装起来 separator:是各个元素的分隔符
  接口中定义方法: public interface StudentMapper {     int batchDeleteStudent(List list); }
  新建测试类: public class Test {     public static void main(String[] args) throws IOException {         final Logger logger = Logger.getLogger(Test.class);         InputStream is = Resources.getResourceAsStream("mybatis-config.xml");          SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);         SqlSession session = sqlSessionFactory.openSession();         StudentMapper mapper = session.getMapper(StudentMapper.class);          List list = new ArrayList<>();         list.add(1);         list.add(2);          mapper.batchDeleteStudent(list);         session.commit();     } }
  运行结果如下:
  4.5 Mybaits分页4.5.1 RowBounds分页
  Mybatis具有分页功能,其为开发者提供了一个类RowBounds,开发者可以使用RowBounds分页,但是RowBounds分页有一个很重要的缺陷,就是会将所有的数据查询出来后根据从第几条到第几条取出数据返回,当数据量比较小时,这么做没有任何问题,但是当数据量大时,这么做无疑对数据库造成了很大的负担。   RowBounds主要定义了两个参数,offset和limit,offset代表从第几行开始读取数据,limit则是限制返回的记录数。在默认情况下offset设置为0,而limit这是Java所允许的最大整数(2147483647)。  下面通过示例学习RowBounds的用法:
  在接口中定义方法: public interface StudentMapper {     List findStudentByPage(RowBounds rowBounds); }
  新建测试类: public class Test {     public static void main(String[] args) throws IOException {         final Logger logger = Logger.getLogger(Test.class);         InputStream is = Resources.getResourceAsStream("mybatis-config.xml");          SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);         SqlSession session = sqlSessionFactory.openSession();         StudentMapper mapper = session.getMapper(StudentMapper.class); 		//1.         List list = mapper.findStudentByPage(new RowBounds(0,5));         list.forEach(e->logger.info(e));     } }
  在代码中注释1处,调用方法是传入RowBounds对象。即可完成分页。   运行结果如下:
  从结果中可以看出使用RowBounds分页时,会将所有的数据都查询出来,然后从数据中截取目标数据,也就是通常所说的逻辑分页。4.5.2 插件分页
  基于RowBounds分页存在一定缺陷,通常会推荐使用自定义插件分页,并且又第三方提供了性能不错的分页插件PageHelper,下面就改插件做简单示范:   首先,在pom.xml中添加依赖     com.github.pagehelper     pagehelper     最新版本 
  在Mybatis全局文件中进行配置:            
  由于Mybatis的插件是基于代理拦截实现,所以继续使用上例中的接口及测试类,插件会自动帮助开发者在SQL中拼接limit关键字。运行结果如下:
  关于该插件的详细用法,可前往PageHelper插件官网进行查阅。

探访老挝的大城市,市区让中国人有些意外提到老挝大城市,就要说说琅勃拉,它是越南富有文化底蕴的城市,虽作为老挝第二大城市,但琅勃拉还是比较安逸稳定的,少了点城市的喧闹,多了点乡野安静的气氛。(此处已添加小程序,请到今日头正式确定!篮坛名将指教国家队,多年致力青训,冲击最终冠军近期,U18女篮即将要征战亚青赛,而近期也正式确定了著名的篮坛名将李昕将会指导国家队进行这一赛事的比赛。众所周知,李昕是一个实力十分强劲的篮球运动员,在选择转型教练后也是十分的负责明星的早期照片,谢霆锋土,杨颖非主流,都是黑历史别看现在的明星个个都是光鲜亮丽,殊不知出道早期的他们也土过,早期照片暴露了他们之前的风格,非主流土潮风格应有尽有。杨幂杨幂早期出道时,也贡献出了不少雷人照片,气质和现在也大不同。从美国在1969年就实现了载人登月,为何过了50多年却难以实现现在美国又重启了搁浅50多年的载人登月计划,却为何在50多年后,难以实现再次登月?难道美国之前的登月计划都是假的吗?美国不是积累了很多的载人登月技术了吗?相信有很多人都会有这样的疑研究揭示啮齿动物漂洋过海到澳大利亚的历史来源新华社新华社堪培拉9月5日电(记者岳东兴)澳大利亚国立大学等机构研究人员在新一期美国当代生物学杂志上发表论文说,通过分析澳大利亚大陆和南太平洋岛屿150多种啮齿动物的脱氧核糖核解析雪峰山旅游发展密码读懂雪峰之子的富民传奇来源中国网旅游作者伍策一丁夏喜衡点睛陈黎明说,我就是个山里人,雪峰山是我的根。所以,我把我人生中最重要的二次创业放在这里。毕竟,自小到大,雪峰山文化已经浸入我的骨髓里。在乡村振兴的泰国旅游男性游客要注意夜晚谨防泰妹套路,否则会吃大亏俗话说害人之心不可有,防人之心不可无。(此处已添加小程序,请到今日头条客户端查看)其实身在异国他乡游玩的时候,游客们更好牢记这一点。泰国作为全球旅游资源十分丰富的大国,由于当地不仅万顺叫车赴美上市,去年收入规模高达50亿元近日,有媒体报道,万顺叫车近期与境外特殊目的公司达成合作协议,拟以SPAC方式最快年内在美国上市。据爱企查App显示,万顺叫车所属企业为深圳万顺叫车云信息技术有限公司,该公司成立于荣耀推出MagicOS!赵明要用开放生态竞争iOS中芯国际奖励独董吴汉明价值约356万元股票(全球TMT2022年9月6日讯)今日要点荣耀推出MagicOS!赵明要用开放生态竞争iOS中芯国际奖励独董吴汉明价值约356万元股票吉利手机将直连低轨卫星。荣耀推出MagicOS7月中国游戏厂商及应用出海EMEA地区收入30强腾讯莉莉丝冠亚军根据data。ai的7月EMEA(欧洲中东与非洲)地区出海收入排行榜,前3名稳定不变,由腾讯莉莉丝IM30持续占领榜单。米哈游凭藉旗下游戏原神的出色表现,在收入榜中跃升到第4名。原2022环球旅游文化小姐唐程瑶因为旅行所以遇见相约环球,遇见唯一的你!2022环球旅游文化小姐唐程瑶环球记者站醉美家乡环球小记者你的家乡在哪里?唐程瑶黑龙江环球小记者请推荐家乡的3种美食?唐程瑶锅包肉地三鲜和小
奔四奔五的中年女人,日常多穿以下4种衣服,提升气质就变简单了女人到了奔四奔五的年纪,有很多事情是无法掌控的。就比如颜值,再贵的护肤品,也拯救不了面部的皱纹松弛的皮肤再比如身材,即使天天健身天天节食,身上也多多少少有些赘肉。但也有些事情是掌控中年女人如何提升魅力?衣服在精不在多,基础款也能很时髦气质女人一到中年,皮肤容貌身材等各方面都有了明显的下降趋势。那么,中年女人如何提升自身魅力呢?建议从穿搭入手,衣服在精不在多,基础款也能很时髦气质!人到中年,日常穿衣还是以简约为主,多中老年人生活别太节俭!多吃5种高蛋白食物,身体倍棒人到了中年以后,就应该把自己的健康放在第一位,没有什么比健康更重要的东西了。可是,矛盾问题也来了,中老年人都是非常节俭的,不愿意吃好的喝好的,总之就是舍不得花钱。人到了一定的年纪,独家淘宝开首家服装集合店电商还能分到线下红利吗电商的实体梦一直都在。近日,北京商报记者独家了解到,淘宝时尚iFashion集合店恢复了正常营业时间。该门店为淘宝在上海落地的首家服装集合店,入驻品牌均为iFashion打标的淘宝挖角成功!前恒大巨星孔卡高调宣布二婚前妻儿子开心吃蛋糕还记得前中超巨星孔卡吗?他又结婚了。孔卡与新女友宣布了婚讯,也举办了一个小型的结婚庆典。孔卡是中国足球历史上最成功的外援之一,帮助恒大取得过亚冠冠军,也统治了中超,之后加盟上海上港玩转复苏纺织服装化妆品化妆品1国货化妆品所处发展阶段以及未来的趋势2014年以前化妆品行业增速比较慢,整体状态是外资品牌依靠多年积淀的品牌壁垒占据了高端市场,渠道以线下高端百货为主,价格比较坚挺。产品形除了蔚来车主,谁会买蔚来手机?本文来自微信公众号车市物语(IDautostinger),作者爱德华,题图来自视觉中国每年开发一款全新手机。作出这个表态的人,不是善于打磨产品的小米雷军,也不是年年9月发新品的苹果自研芯片售价1400美元,谷歌首款折叠屏手机三季度量产8月8日据调研机构DSCC相关负责人透露,谷歌即将进军折叠手机市场。谷歌正打算推出两款旗舰手机,一款为折叠设计,市场暂时定名为PixelNotepad,另一款则是高端Pixel手机机构中国大陆智能手机厂商Q2出货季减5。2vivo跌幅最大集微网消息,根据DIGITIMESResearch的SmartphoneTracker的数据,第二季度中国大陆智能手机厂商总出货量约为1。5亿台,季减5。2,年减4。6。据台媒电子订单已破6万,比亚迪海豹的热销已成定局,能否超越Model3?7月29日,比亚迪海豹正式上市。定位是中型纯电动轿车,四款车型的售价区间为20。98万28。68万元。比亚迪海豹不仅是比亚迪汽车今年推出的重磅车型,而且也是自主品牌车型中非常重要的摩托罗拉8月11日发布新品,三款手机要发布摩托罗拉新品会在8月11日发布,有三款新品要发布,简单看看吧。这三款新品是摩托罗拉razr2022,x30pro和s30pro,这三款里面一款是折叠屏,一款是旗舰手机,一款是性价比