首页 / 资讯中心 / 文章详情

MyBatis(随笔: 动态SQL映射文件)

MyBatis(随笔: 动态SQL映射文件) ★ FEATURED ARTICLE
动态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
阅读完成 · 觉得有帮助?
咨询建站