动态SQL我们可以用mybatis执行sql的形式来对数据的表进行增删改查操作不过遇到比较复杂的业务需要写复杂的sql时比如说sql的条件不确定可能有一个条件或者多个我们就需要动态sql来提高sql的灵活性。基于OGNL表达式完成多条件查询等逻辑实现用于实现动态SQL的元素主要有if , trim , where , set , choosewhen、otherwise, foreach 示例代码 Demo.查询用户表 跟名称 密码 地址做多条件查询Java接口UserMapper.java//动态Sql// 1. if where trim// 查询用户表 跟名称 密码 地址做多条件查询//如果参数过多可以使用 Map;publicListUsercha(Param(name)Stringname,Param(pwd)Stringpwd,Param(address)Stringaddress);映射文件UserMapper.XMLif 完成多条件查询!-- 方式一if --selectidcharesultTypeUserSELECT * FROM smbms_user WHERE 11!-- 为了保证拼接 where 11 如果if成立 and拼接,不成立也不会因为 where后面啥也没有而报错 --iftestname!null and name!AND userName LIKE CONCAT(%,#{name},%)/ififtestpwd!null and pwd!AND userPassword LIKE CONCAT(%,#{pwd},%)/ififtestaddress!null and address!AND address LIKE CONCAT(%,#{address},%)/if/select!-- 使用 if 进行动态sql处理 test: 使用OGNL表达式,进行验证参数而拼接对应的 sql 语句; 对于参数,不建议使用 parameterType 传单个参数,可以是 Map|复杂数据类型,而单个参数因为没有参数名所以 OGNL表达式无法表示进行判断...可以使用注解.. --where 完成多条件查询!-- 方式二 where --selectidcharesultTypeUserSELECT * FROM smbms_userwhereiftestname!null and name!AND userName LIKE CONCAT(%,#{name},%)/ififtestpwd!null and pwd!AND userPassword LIKE CONCAT(%,#{pwd},%)/ififtestaddress!null and address!AND address LIKE CONCAT(%,#{address},%)/if/where/select!-- 使用 whereif 进行动态sql处理 if就不介绍了 where: 这里sql语句上面就不需要加 where 11防止拼接错误了. 因为: where 会自动在第一个 if成立的sql前面加 where 并移除它的and而之后的不会有影响; --trim 完成多条件查询!-- 方式三: trim --selectidcharesultTypeUserSELECT * FROM smbms_usertrimprefixwhereprefixOverridesand|or!-- 第一个成立if 新增where 剪切 and 或 or --iftestname!null and name!AND userName LIKE CONCAT(%,#{name},%)/ififtestpwd!null and pwd!AND userPassword LIKE CONCAT(%,#{pwd},%)/ififtestaddress!null and address!AND address LIKE CONCAT(%,#{address},%)/if/trim/select!-- 使用 trimif 进行动态sql处理 if就不介绍了 trim : 类似于一个可以自定义的标签,这里就相当于将 trim 设置为一个类似 where标签; 更灵活地去除多余关键字,替代where和set prefix 代表的是语句的前缀会在第一个成立if sql前面加 prefix的值; suffix 代表的是语句的后缀会在最后一个成立if sql后面加 suffix的值; prefixOverrides 代表的是需要去掉的字符串,会在第一个成立if 剪切sql中 prefixOverrides的值; suffixOverrides 代表的是语句的后缀会在最后一个成立if 剪切sql中 suffixOverrides的值; --修改用户表 使用if set trimJava接口UserMapper.java//2.修改用户表 使用if set frimpublicintupd(Useru);映射文件UserMapper.XMLset 完成修改updateidupdparameterTypeUserUPDATE smbms_usersetiftestuserName!null and userName!userName #{userName},/ififtestuserPassword!null and userPassword!userPassword#{userPassword},/if/setwhere id #{id}/update--!-- set: 会默认在第一个成立if 前面加SET,并去掉最后一个列的 , 逗号 注意要确保至少有一个set 成立哦~不然 UPDATE 表 WHERE ID? 并不符合Sql语句!,没有一个if成立导致没有 SET要修改的列; --trim 完成修改updateidupdparameterTypeUserUPDATE smbms_usertrimprefixsetsuffixwhere id #{id}suffixOverrides,iftestuserName!null and userName!userName #{userName},/ififtestuserPassword!null and userPassword!userPassword#{userPassword},/if/trim/updatein查询用户表 使用foreach 完成部门查询;Java接口UserMapper.java// 3.in查询用户表 使用foreach 完成部门查询;publicListUserchain(ListIntegeruserRoles);映射文件UserMapper.XML!-- 3.in查询用户表 使用fearche 完成部门查询; --selectidchainparameterTypejava.util.ListresultTypeUserSELECT * FROM smbms_user WHERE userRole INforeachcollectionlistitemWopen(close)separator,#{W}/foreach/select!-- foreach: 迭代一个集合通常用于in条件 item 表示集合中每一个元素进行迭代时候的别名; index 指定一个名称,用于表示在迭代过程中每次迭代到的位置。 collection:必须指定: list集合 当传入参数是单参数且是一个list时候 collection属性值应该为 list; array数组: 当传入参数是单参数且是一个数组时候collection属性值应该为array map-key集合: 当传入参数为多参数,就需要包它们封装为一个Map进行处理; open 表示该语句开始时候的符合,既然是in 那一定是 open( separator 表示在每次进行迭代之间什么符号,作为分隔符 既然是in 那一定是 separator, close 表示该语句结束时候的符合,既然是in 那一定是 close) --对于某些查询需求,虽然有多个查询条件,但我们不想应用所有的条件,只选择其中一种查询结果时候可以使用Choose;Java接口UserMapper.java//5.对于某些查询需求,虽然有多个查询条件,但我们不想应用所有的条件,只选择其中一种查询结果时候可以使用Choose;//用户名模糊查询 | 密码模糊查询 都不符合则查全部;publicListUserchoose(Param(name)Stringname,Param(pwd)Stringpwd);映射文件UserMapper.XML!-- 用户名模糊查询 | 密码模糊查询 都不符合则查全部; --!-- Choose --selectidchooseresultTypeUserSELECT * FROM smbms_userwherechoosewhentestname!null and name!AND userName LIKE CONCAT(%,#{name},%)/whenwhentestpwd!null and pwd!AND userPassword LIKE CONCAT(%,#{pwd},%)/whenotherwiseand 11/otherwise/choose/where/select!-- choose(when、otherwise): 相当于Java中switch语句,当when有条件满足的时候就跳出choose,如果没有一个成立则执行: otherwise; choose when test 条件1 …/when when test 条件2 …/when ..... otherwise…/otherwise /choose --运行类DTSqlRun .Javapackagecom.wsm.run;importjava.util.ArrayList;importjava.util.List;importjava.util.Scanner;importorg.apache.ibatis.session.SqlSession;importcom.wsm.mapper.UserMapper;importcom.wsm.pojo.User;importcom.wsm.utis.MyBatisUtil;publicclassDTSqlRun{staticScannerinputnewScanner(System.in);publicstaticvoidmain(String[]args){DTSqlRunrnewDTSqlRun();//r.cha();//r.upd();//r.chain();r.choose();}publicvoidcha(){SqlSessionsessionMyBatisUtil.create();UserMapperumsession.getMapper(UserMapper.class);ListUserusersum.cha(w,null,);if(users.size()0){System.out.println(没有数据);}for(Useruser:users){System.out.println(user.getId()\tuser.getUserCode()\tuser.getUserName()\tuser.getPhone()\tuser.getAddress());}MyBatisUtil.close(session);}publicvoidupd(){UserunewUser();//u.setUserName(asdsasad);u.setUserPassword(xxasssssda);u.setId(1);SqlSessionsessionMyBatisUtil.create();UserMapperumsession.getMapper(UserMapper.class);if(um.upd(u)1){session.commit();//手动提交;System.out.println(修改成功);}else{System.out.println(修改失败);}MyBatisUtil.close(session);}publicvoidchain(){ListIntegerinnewArrayListInteger();in.add(1);in.add(2);//in.add(3);SqlSessionsessionMyBatisUtil.create();UserMapperumsession.getMapper(UserMapper.class);ListUserusersum.chain(in);if(users.size()0){System.out.println(没有数据);}for(Useruser:users){System.out.println(user.getId()\tuser.getUserCode()\tuser.getUserName()\tuser.getPhone()\tuser.getAddress()\tuser.getUserRole());}MyBatisUtil.close(session);}publicvoidchoose(){SqlSessionsessionMyBatisUtil.create();UserMapperumsession.getMapper(UserMapper.class);ListUserusersum.choose(s,ss);//两个参数都传了,但pwd的属性无效,因为name 成立了 choose 就结束了;if(users.size()0){System.out.println(没有数据);}for(Useruser:users){System.out.println(user.getId()\tuser.getUserCode()\tuser.getUserName()\tuser.getPhone()\tuser.getAddress());}MyBatisUtil.close(session);}}MyBatis缓存正如大多数框架一样MyBatis提供了一级缓存和二级缓存一级缓存一级缓存是基于,PerpetyalCache(MyBatis 自带的), HashMap本地缓存作用范围在 SqlSession域内. 当SqlSession关闭时,则其所有的缓存就会被清空…二级缓存二级缓存就是 global caching 它超出 sqlsession 范围之外, 结果可以被所有的sqlSession 共享;开启它只需要在MyBatis 的核心配置文件( MyBatis-config.xml ) setting 中设置…二级缓存的配置1.需要在MyBatis-config.xml中配置settings!--配置mybatis的log实现为LOG4J --settingnamelogImplvalueLOG4J/!--设置resultMap的自动映射级别NONE(禁止自动匹配),PARTIAL(默认)自动匹配所有属性,有内部嵌套(association、collection)的除外 且 数据库列与实体类名相同,FULL(自动匹配所有属性)比PARTIAL更强 --settingnameautoMappingBehaviorvalueFULL/!-- 设置二级缓存 --settingnamecacheEnabledvaluetrue//settings2.在对应的Mapper.xml 文件中设置缓存默认是没有开启缓存的;需要注意的是global caching 作用域针对的是 mapper 的 namespace 而言的,即只有在此 namepace 内的查询才可以共享这个 cache…cacheevictionFIFOflushInterval60000size512readOnlytrue/!-- 二级缓存 --!-- eviction 文件的保存形式; flushInterval 缓存对象的毫秒数; size 缓存对象的个数; 先进先出原则,如果已经满了,则最先进的移除,添加新的 readOnly : 只读 --3.在 mapper 文件配置支持 cache 后, 如果需要对个别查询进行调整可以单独设置 cache 代码这样就不需要在配置 Cache了…方法2 和 方法3可以选一种...!-- userCache: true开启 false关闭; --selectidcharesultMapRoleMapuseCachetrue.../select示例demo//根据编号查部门及 部门员工;publicvoidcha(){SqlSessionsessionMyBatisUtil.create();RoleMapperrmsession.getMapper(RoleMapper.class);//一级缓存缓存数据存储在 sqlSession中;Rolerrm.cha(2);System.out.println(r.getRoleName()\tr.getId());ListUserur.getUsers();for(Useruser:u){System.out.println(user.getUserName());}//因此不关闭 sqlSession 在此查相同的数据不会在需要sql语句; 访问数据库;System.out.println(------------------------------------------);Roler1rm.cha(2);System.out.println(r1.getRoleName()\tr1.getId());//而查询没有查过的数据还是需要sql 访问数据库System.out.println(------------------------------------------);Roler2rm.cha(3);System.out.println(r2.getRoleName()\tr2.getId());MyBatisUtil.close(session);//关闭SqlSessionSystem.out.println(二级缓存);//二级缓存: 数据存储在 sqlSessionFactory工厂中;//需要在配置信息中设置//MyBatis: setting namecacheEnabled valuetrue///xxxMapper.xml中 cache evictionFIFO flushInterval60000 size512 readOnlytrue///而查询时: select idcha resultMapRoleMap useCachetrue 即可;!! useCachetrue/false 开启/关闭;//即使是SqlSession 关闭对于查过的数据也会保存起来SqlSessionsessionrMyBatisUtil.create();RoleMapperrmrsessionr.getMapper(RoleMapper.class);Rolerrrmr.cha(1);System.out.println(rr.getRoleName()\trr.getId());MyBatisUtil.close(sessionr);//关闭SqlSession//上面关闭了,才用二级缓存;所以不在需要Sql 数据库操作;SqlSessionsessionr1MyBatisUtil.create();RoleMapperrmr1sessionr1.getMapper(RoleMapper.class);Rolerr1rmr1.cha(1);System.out.println(rr1.getRoleName()\trr1.getId());MyBatisUtil.close(sessionr1);//关闭SqlSession}Run
企业数字化 ERP 产品动态
相关推荐
Spring配置补充 (随笔详情扩展:) Spring配置补充:
实现Spring 和 MyBatis 集成过程中学习了,Spring 的配置数据源的方法; 实际开发过程中还有很多灵活的配置文件;
灵活配置DataSource:
<!-- 远古方法(最初方法),数据库连接池,不过我最喜欢用的; --><bean id"… · 2026/11/6 4:49:50
初始MyBatis(随笔1) 初始MyBatis(随笔1)
框架技术
为什么要学习框架技术: PTT模板举例:做ppt前, 总是会需要找一些模板, 优点; 1. 不用考虑布局, 排版等问题, 提高了效率; 2. 可以专心于PTT的内容, 使演讲 “质量” 更有保障; 3. 新手也可以实现出很好的 PPT; 框架&#x… · 2026/11/6 4:49:50
外地考高压电工证多久拿证最稳妥?别怕考不过白交培训费 外地考高压电工证多久拿证最稳妥?别怕考不过白交培训费 怕考不过白交培训费?那你得先搞清楚高压电工证怎么考、多久能拿证、外地人怎么操作不踩坑。别急,我给你说透,省时省力又省钱。… · 2026/11/7 10:07:01
工地太忙根本没时间复习考试 桥架电工证怎么报名全攻略 工地太忙根本没时间复习考试 桥架电工证怎么报名全攻略 工地上的节奏快得像在跑马拉松,活儿干不完,考试还卡着脖子。你可能正为【桥架电工证】怎么报名犯愁,更别提抽时间复习了。别急,这篇文章专门为你准备,从报名流程到备考技巧,一套搞定。… · 2026/11/7 10:07:01
台儿庄区哪里考电工证内部消息全公开别再交冤枉钱 台儿庄区哪里考电工证内部消息全公开别再交冤枉钱 怕考不过白交培训费?台儿庄区哪里考电工证?很多电工朋友都遇到过这样的情况,选错了培训机构,花了几千块,结果考试没过,证也没拿到,钱打水漂。这年头, 电工证… · 2026/11/7 10:07:01
六枝特区电工证怎么考?上岗必备证书的全流程干货 六枝特区电工证怎么考?上岗必备证书的全流程干货 你是不是正被“急需特种作业证才能上岗找工作”的问题折磨?别急,六枝特区电工证就是你求职路上的“上岗必备”利器。今天我从一个过来人角度,告诉你怎么在六枝特区考电工证、怎么备考、怎么复习,帮你少走… · 2026/11/7 10:07:01
低学历也能考寿县特种作业操作证?含金量高到你想不到 低学历也能考寿县特种作业操作证?含金量高到你想不到 你是不是也担心学历不高报不了名?别急,寿县特种作业操作证报考门槛其实没你想的那么高,只要符合条件, 含金量 照样够硬。今天就带你扒一扒这个证到底值不值得考,还能帮你避开那些坑。… · 2026/11/7 10:07:01
电工证复审多久开始内部消息曝光!别再被中介骗了 电工证复审多久开始内部消息曝光!别再被中介骗了 你是不是也遇到过这种情况,电工证快到期了,不知道去哪儿复审,生怕被中介坑钱?电工证复审多久开始这个问题,其实每年都有明确的规定,但很多人还是搞不清。今天我就来给你透露 内部消息… · 2026/11/7 10:06:00
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:27:59
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:28:03
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/6 10:29:23
澳洲水电工证考试:证书过期了不知道怎么复审延期?电子证书怎么弄? 澳洲水电工证考试:证书过期了不知道怎么复审延期?电子证书怎么弄? 证书过期了不知道怎么复审延期?别慌,很多人在拿到【澳洲水电工证考试】的电子证书后,一不小心就忽略了复审时间,结果证书失效,工作受阻,甚至被单位追责。今天就从【澳洲水电工证考试… · 2026/11/7 0:00:41
电工作业提示版通过率揭秘:怎么考才能一次过? 电工作业提示版通过率揭秘:怎么考才能一次过? 怕考不过白交培训费?别急,今天我就从驻马店应届工程类毕业生的视角,带你全面了解电工作业提示版的考试流程、备考要点和真实通过率,帮你少走弯路、提高一次通过率。… · 2026/11/7 0:00:41
电工证年审报名千万别踩坑 外省证转过来要搞清这几点 电工证年审报名千万别踩坑 外省证转过来要搞清这几点 之前考的证在外省能不能转过来?这个问题是很多电工从业者最关心的,特别是像你这样在商丘从事公路工程的人员,经常需要跨省流动,证书的 有效性 和 可迁移性… · 2026/11/7 0:00:41
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:27:59
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:28:03
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/6 10:29:23